protocol.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // Copyright 2020 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package snap
  17. import (
  18. "errors"
  19. "fmt"
  20. "github.com/ethereum/go-ethereum/common"
  21. "github.com/ethereum/go-ethereum/core/state/snapshot"
  22. "github.com/ethereum/go-ethereum/rlp"
  23. )
  24. // Constants to match up protocol versions and messages
  25. const (
  26. SNAP1 = 1
  27. )
  28. // ProtocolName is the official short name of the `snap` protocol used during
  29. // devp2p capability negotiation.
  30. const ProtocolName = "snap"
  31. // ProtocolVersions are the supported versions of the `snap` protocol (first
  32. // is primary).
  33. var ProtocolVersions = []uint{SNAP1}
  34. // protocolLengths are the number of implemented message corresponding to
  35. // different protocol versions.
  36. var protocolLengths = map[uint]uint64{SNAP1: 8}
  37. // maxMessageSize is the maximum cap on the size of a protocol message.
  38. const maxMessageSize = 10 * 1024 * 1024
  39. const (
  40. GetAccountRangeMsg = 0x00
  41. AccountRangeMsg = 0x01
  42. GetStorageRangesMsg = 0x02
  43. StorageRangesMsg = 0x03
  44. GetByteCodesMsg = 0x04
  45. ByteCodesMsg = 0x05
  46. GetTrieNodesMsg = 0x06
  47. TrieNodesMsg = 0x07
  48. )
  49. var (
  50. errMsgTooLarge = errors.New("message too long")
  51. errDecode = errors.New("invalid message")
  52. errInvalidMsgCode = errors.New("invalid message code")
  53. errBadRequest = errors.New("bad request")
  54. )
  55. // Packet represents a p2p message in the `snap` protocol.
  56. type Packet interface {
  57. Name() string // Name returns a string corresponding to the message type.
  58. Kind() byte // Kind returns the message type.
  59. }
  60. // GetAccountRangePacket represents an account query.
  61. type GetAccountRangePacket struct {
  62. ID uint64 // Request ID to match up responses with
  63. Root common.Hash // Root hash of the account trie to serve
  64. Origin common.Hash // Hash of the first account to retrieve
  65. Limit common.Hash // Hash of the last account to retrieve
  66. Bytes uint64 // Soft limit at which to stop returning data
  67. }
  68. // AccountRangePacket represents an account query response.
  69. type AccountRangePacket struct {
  70. ID uint64 // ID of the request this is a response for
  71. Accounts []*AccountData // List of consecutive accounts from the trie
  72. Proof [][]byte // List of trie nodes proving the account range
  73. }
  74. // AccountData represents a single account in a query response.
  75. type AccountData struct {
  76. Hash common.Hash // Hash of the account
  77. Body rlp.RawValue // Account body in slim format
  78. }
  79. // Unpack retrieves the accounts from the range packet and converts from slim
  80. // wire representation to consensus format. The returned data is RLP encoded
  81. // since it's expected to be serialized to disk without further interpretation.
  82. //
  83. // Note, this method does a round of RLP decoding and reencoding, so only use it
  84. // once and cache the results if need be. Ideally discard the packet afterwards
  85. // to not double the memory use.
  86. func (p *AccountRangePacket) Unpack() ([]common.Hash, [][]byte, error) {
  87. var (
  88. hashes = make([]common.Hash, len(p.Accounts))
  89. accounts = make([][]byte, len(p.Accounts))
  90. )
  91. for i, acc := range p.Accounts {
  92. val, err := snapshot.FullAccountRLP(acc.Body)
  93. if err != nil {
  94. return nil, nil, fmt.Errorf("invalid account %x: %v", acc.Body, err)
  95. }
  96. hashes[i], accounts[i] = acc.Hash, val
  97. }
  98. return hashes, accounts, nil
  99. }
  100. // GetStorageRangesPacket represents an storage slot query.
  101. type GetStorageRangesPacket struct {
  102. ID uint64 // Request ID to match up responses with
  103. Root common.Hash // Root hash of the account trie to serve
  104. Accounts []common.Hash // Account hashes of the storage tries to serve
  105. Origin []byte // Hash of the first storage slot to retrieve (large contract mode)
  106. Limit []byte // Hash of the last storage slot to retrieve (large contract mode)
  107. Bytes uint64 // Soft limit at which to stop returning data
  108. }
  109. // StorageRangesPacket represents a storage slot query response.
  110. type StorageRangesPacket struct {
  111. ID uint64 // ID of the request this is a response for
  112. Slots [][]*StorageData // Lists of consecutive storage slots for the requested accounts
  113. Proof [][]byte // Merkle proofs for the *last* slot range, if it's incomplete
  114. }
  115. // StorageData represents a single storage slot in a query response.
  116. type StorageData struct {
  117. Hash common.Hash // Hash of the storage slot
  118. Body []byte // Data content of the slot
  119. }
  120. // Unpack retrieves the storage slots from the range packet and returns them in
  121. // a split flat format that's more consistent with the internal data structures.
  122. func (p *StorageRangesPacket) Unpack() ([][]common.Hash, [][][]byte) {
  123. var (
  124. hashset = make([][]common.Hash, len(p.Slots))
  125. slotset = make([][][]byte, len(p.Slots))
  126. )
  127. for i, slots := range p.Slots {
  128. hashset[i] = make([]common.Hash, len(slots))
  129. slotset[i] = make([][]byte, len(slots))
  130. for j, slot := range slots {
  131. hashset[i][j] = slot.Hash
  132. slotset[i][j] = slot.Body
  133. }
  134. }
  135. return hashset, slotset
  136. }
  137. // GetByteCodesPacket represents a contract bytecode query.
  138. type GetByteCodesPacket struct {
  139. ID uint64 // Request ID to match up responses with
  140. Hashes []common.Hash // Code hashes to retrieve the code for
  141. Bytes uint64 // Soft limit at which to stop returning data
  142. }
  143. // ByteCodesPacket represents a contract bytecode query response.
  144. type ByteCodesPacket struct {
  145. ID uint64 // ID of the request this is a response for
  146. Codes [][]byte // Requested contract bytecodes
  147. }
  148. // GetTrieNodesPacket represents a state trie node query.
  149. type GetTrieNodesPacket struct {
  150. ID uint64 // Request ID to match up responses with
  151. Root common.Hash // Root hash of the account trie to serve
  152. Paths []TrieNodePathSet // Trie node hashes to retrieve the nodes for
  153. Bytes uint64 // Soft limit at which to stop returning data
  154. }
  155. // TrieNodePathSet is a list of trie node paths to retrieve. A naive way to
  156. // represent trie nodes would be a simple list of `account || storage` path
  157. // segments concatenated, but that would be very wasteful on the network.
  158. //
  159. // Instead, this array special cases the first element as the path in the
  160. // account trie and the remaining elements as paths in the storage trie. To
  161. // address an account node, the slice should have a length of 1 consisting
  162. // of only the account path. There's no need to be able to address both an
  163. // account node and a storage node in the same request as it cannot happen
  164. // that a slot is accessed before the account path is fully expanded.
  165. type TrieNodePathSet [][]byte
  166. // TrieNodesPacket represents a state trie node query response.
  167. type TrieNodesPacket struct {
  168. ID uint64 // ID of the request this is a response for
  169. Nodes [][]byte // Requested state trie nodes
  170. }
  171. func (*GetAccountRangePacket) Name() string { return "GetAccountRange" }
  172. func (*GetAccountRangePacket) Kind() byte { return GetAccountRangeMsg }
  173. func (*AccountRangePacket) Name() string { return "AccountRange" }
  174. func (*AccountRangePacket) Kind() byte { return AccountRangeMsg }
  175. func (*GetStorageRangesPacket) Name() string { return "GetStorageRanges" }
  176. func (*GetStorageRangesPacket) Kind() byte { return GetStorageRangesMsg }
  177. func (*StorageRangesPacket) Name() string { return "StorageRanges" }
  178. func (*StorageRangesPacket) Kind() byte { return StorageRangesMsg }
  179. func (*GetByteCodesPacket) Name() string { return "GetByteCodes" }
  180. func (*GetByteCodesPacket) Kind() byte { return GetByteCodesMsg }
  181. func (*ByteCodesPacket) Name() string { return "ByteCodes" }
  182. func (*ByteCodesPacket) Kind() byte { return ByteCodesMsg }
  183. func (*GetTrieNodesPacket) Name() string { return "GetTrieNodes" }
  184. func (*GetTrieNodesPacket) Kind() byte { return GetTrieNodesMsg }
  185. func (*TrieNodesPacket) Name() string { return "TrieNodes" }
  186. func (*TrieNodesPacket) Kind() byte { return TrieNodesMsg }