protocol.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. errCancelled = errors.New("sync cancelled")
  55. )
  56. // Packet represents a p2p message in the `snap` protocol.
  57. type Packet interface {
  58. Name() string // Name returns a string corresponding to the message type.
  59. Kind() byte // Kind returns the message type.
  60. }
  61. // GetAccountRangePacket represents an account query.
  62. type GetAccountRangePacket struct {
  63. ID uint64 // Request ID to match up responses with
  64. Root common.Hash // Root hash of the account trie to serve
  65. Origin common.Hash // Hash of the first account to retrieve
  66. Limit common.Hash // Hash of the last account to retrieve
  67. Bytes uint64 // Soft limit at which to stop returning data
  68. }
  69. // AccountRangePacket represents an account query response.
  70. type AccountRangePacket struct {
  71. ID uint64 // ID of the request this is a response for
  72. Accounts []*AccountData // List of consecutive accounts from the trie
  73. Proof [][]byte // List of trie nodes proving the account range
  74. }
  75. // AccountData represents a single account in a query response.
  76. type AccountData struct {
  77. Hash common.Hash // Hash of the account
  78. Body rlp.RawValue // Account body in slim format
  79. }
  80. // Unpack retrieves the accounts from the range packet and converts from slim
  81. // wire representation to consensus format. The returned data is RLP encoded
  82. // since it's expected to be serialized to disk without further interpretation.
  83. //
  84. // Note, this method does a round of RLP decoding and reencoding, so only use it
  85. // once and cache the results if need be. Ideally discard the packet afterwards
  86. // to not double the memory use.
  87. func (p *AccountRangePacket) Unpack() ([]common.Hash, [][]byte, error) {
  88. var (
  89. hashes = make([]common.Hash, len(p.Accounts))
  90. accounts = make([][]byte, len(p.Accounts))
  91. )
  92. for i, acc := range p.Accounts {
  93. val, err := snapshot.FullAccountRLP(acc.Body)
  94. if err != nil {
  95. return nil, nil, fmt.Errorf("invalid account %x: %v", acc.Body, err)
  96. }
  97. hashes[i], accounts[i] = acc.Hash, val
  98. }
  99. return hashes, accounts, nil
  100. }
  101. // GetStorageRangesPacket represents an storage slot query.
  102. type GetStorageRangesPacket struct {
  103. ID uint64 // Request ID to match up responses with
  104. Root common.Hash // Root hash of the account trie to serve
  105. Accounts []common.Hash // Account hashes of the storage tries to serve
  106. Origin []byte // Hash of the first storage slot to retrieve (large contract mode)
  107. Limit []byte // Hash of the last storage slot to retrieve (large contract mode)
  108. Bytes uint64 // Soft limit at which to stop returning data
  109. }
  110. // StorageRangesPacket represents a storage slot query response.
  111. type StorageRangesPacket struct {
  112. ID uint64 // ID of the request this is a response for
  113. Slots [][]*StorageData // Lists of consecutive storage slots for the requested accounts
  114. Proof [][]byte // Merkle proofs for the *last* slot range, if it's incomplete
  115. }
  116. // StorageData represents a single storage slot in a query response.
  117. type StorageData struct {
  118. Hash common.Hash // Hash of the storage slot
  119. Body []byte // Data content of the slot
  120. }
  121. // Unpack retrieves the storage slots from the range packet and returns them in
  122. // a split flat format that's more consistent with the internal data structures.
  123. func (p *StorageRangesPacket) Unpack() ([][]common.Hash, [][][]byte) {
  124. var (
  125. hashset = make([][]common.Hash, len(p.Slots))
  126. slotset = make([][][]byte, len(p.Slots))
  127. )
  128. for i, slots := range p.Slots {
  129. hashset[i] = make([]common.Hash, len(slots))
  130. slotset[i] = make([][]byte, len(slots))
  131. for j, slot := range slots {
  132. hashset[i][j] = slot.Hash
  133. slotset[i][j] = slot.Body
  134. }
  135. }
  136. return hashset, slotset
  137. }
  138. // GetByteCodesPacket represents a contract bytecode query.
  139. type GetByteCodesPacket struct {
  140. ID uint64 // Request ID to match up responses with
  141. Hashes []common.Hash // Code hashes to retrieve the code for
  142. Bytes uint64 // Soft limit at which to stop returning data
  143. }
  144. // ByteCodesPacket represents a contract bytecode query response.
  145. type ByteCodesPacket struct {
  146. ID uint64 // ID of the request this is a response for
  147. Codes [][]byte // Requested contract bytecodes
  148. }
  149. // GetTrieNodesPacket represents a state trie node query.
  150. type GetTrieNodesPacket struct {
  151. ID uint64 // Request ID to match up responses with
  152. Root common.Hash // Root hash of the account trie to serve
  153. Paths []TrieNodePathSet // Trie node hashes to retrieve the nodes for
  154. Bytes uint64 // Soft limit at which to stop returning data
  155. }
  156. // TrieNodePathSet is a list of trie node paths to retrieve. A naive way to
  157. // represent trie nodes would be a simple list of `account || storage` path
  158. // segments concatenated, but that would be very wasteful on the network.
  159. //
  160. // Instead, this array special cases the first element as the path in the
  161. // account trie and the remaining elements as paths in the storage trie. To
  162. // address an account node, the slice should have a length of 1 consisting
  163. // of only the account path. There's no need to be able to address both an
  164. // account node and a storage node in the same request as it cannot happen
  165. // that a slot is accessed before the account path is fully expanded.
  166. type TrieNodePathSet [][]byte
  167. // TrieNodesPacket represents a state trie node query response.
  168. type TrieNodesPacket struct {
  169. ID uint64 // ID of the request this is a response for
  170. Nodes [][]byte // Requested state trie nodes
  171. }
  172. func (*GetAccountRangePacket) Name() string { return "GetAccountRange" }
  173. func (*GetAccountRangePacket) Kind() byte { return GetAccountRangeMsg }
  174. func (*AccountRangePacket) Name() string { return "AccountRange" }
  175. func (*AccountRangePacket) Kind() byte { return AccountRangeMsg }
  176. func (*GetStorageRangesPacket) Name() string { return "GetStorageRanges" }
  177. func (*GetStorageRangesPacket) Kind() byte { return GetStorageRangesMsg }
  178. func (*StorageRangesPacket) Name() string { return "StorageRanges" }
  179. func (*StorageRangesPacket) Kind() byte { return StorageRangesMsg }
  180. func (*GetByteCodesPacket) Name() string { return "GetByteCodes" }
  181. func (*GetByteCodesPacket) Kind() byte { return GetByteCodesMsg }
  182. func (*ByteCodesPacket) Name() string { return "ByteCodes" }
  183. func (*ByteCodesPacket) Kind() byte { return ByteCodesMsg }
  184. func (*GetTrieNodesPacket) Name() string { return "GetTrieNodes" }
  185. func (*GetTrieNodesPacket) Kind() byte { return GetTrieNodesMsg }
  186. func (*TrieNodesPacket) Name() string { return "TrieNodes" }
  187. func (*TrieNodesPacket) Kind() byte { return TrieNodesMsg }