github.com/cryptogateway/go-paymex@v0.0.0-20210204174735-96277fb1e602/eth/protocols/snap/protocol.go (about) 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 17 package snap 18 19 import ( 20 "errors" 21 "fmt" 22 23 "github.com/cryptogateway/go-paymex/common" 24 "github.com/cryptogateway/go-paymex/core/state/snapshot" 25 "github.com/cryptogateway/go-paymex/rlp" 26 ) 27 28 // Constants to match up protocol versions and messages 29 const ( 30 snap1 = 1 31 ) 32 33 // ProtocolName is the official short name of the `snap` protocol used during 34 // devp2p capability negotiation. 35 const ProtocolName = "snap" 36 37 // ProtocolVersions are the supported versions of the `snap` protocol (first 38 // is primary). 39 var ProtocolVersions = []uint{snap1} 40 41 // protocolLengths are the number of implemented message corresponding to 42 // different protocol versions. 43 var protocolLengths = map[uint]uint64{snap1: 8} 44 45 // maxMessageSize is the maximum cap on the size of a protocol message. 46 const maxMessageSize = 10 * 1024 * 1024 47 48 const ( 49 GetAccountRangeMsg = 0x00 50 AccountRangeMsg = 0x01 51 GetStorageRangesMsg = 0x02 52 StorageRangesMsg = 0x03 53 GetByteCodesMsg = 0x04 54 ByteCodesMsg = 0x05 55 GetTrieNodesMsg = 0x06 56 TrieNodesMsg = 0x07 57 ) 58 59 var ( 60 errMsgTooLarge = errors.New("message too long") 61 errDecode = errors.New("invalid message") 62 errInvalidMsgCode = errors.New("invalid message code") 63 errBadRequest = errors.New("bad request") 64 errCancelled = errors.New("sync cancelled") 65 ) 66 67 // Packet represents a p2p message in the `snap` protocol. 68 type Packet interface { 69 Name() string // Name returns a string corresponding to the message type. 70 Kind() byte // Kind returns the message type. 71 } 72 73 // GetAccountRangePacket represents an account query. 74 type GetAccountRangePacket struct { 75 ID uint64 // Request ID to match up responses with 76 Root common.Hash // Root hash of the account trie to serve 77 Origin common.Hash // Hash of the first account to retrieve 78 Limit common.Hash // Hash of the last account to retrieve 79 Bytes uint64 // Soft limit at which to stop returning data 80 } 81 82 // AccountRangePacket represents an account query response. 83 type AccountRangePacket struct { 84 ID uint64 // ID of the request this is a response for 85 Accounts []*AccountData // List of consecutive accounts from the trie 86 Proof [][]byte // List of trie nodes proving the account range 87 } 88 89 // AccountData represents a single account in a query response. 90 type AccountData struct { 91 Hash common.Hash // Hash of the account 92 Body rlp.RawValue // Account body in slim format 93 } 94 95 // Unpack retrieves the accounts from the range packet and converts from slim 96 // wire representation to consensus format. The returned data is RLP encoded 97 // since it's expected to be serialized to disk without further interpretation. 98 // 99 // Note, this method does a round of RLP decoding and reencoding, so only use it 100 // once and cache the results if need be. Ideally discard the packet afterwards 101 // to not double the memory use. 102 func (p *AccountRangePacket) Unpack() ([]common.Hash, [][]byte, error) { 103 var ( 104 hashes = make([]common.Hash, len(p.Accounts)) 105 accounts = make([][]byte, len(p.Accounts)) 106 ) 107 for i, acc := range p.Accounts { 108 val, err := snapshot.FullAccountRLP(acc.Body) 109 if err != nil { 110 return nil, nil, fmt.Errorf("invalid account %x: %v", acc.Body, err) 111 } 112 hashes[i], accounts[i] = acc.Hash, val 113 } 114 return hashes, accounts, nil 115 } 116 117 // GetStorageRangesPacket represents an storage slot query. 118 type GetStorageRangesPacket struct { 119 ID uint64 // Request ID to match up responses with 120 Root common.Hash // Root hash of the account trie to serve 121 Accounts []common.Hash // Account hashes of the storage tries to serve 122 Origin []byte // Hash of the first storage slot to retrieve (large contract mode) 123 Limit []byte // Hash of the last storage slot to retrieve (large contract mode) 124 Bytes uint64 // Soft limit at which to stop returning data 125 } 126 127 // StorageRangesPacket represents a storage slot query response. 128 type StorageRangesPacket struct { 129 ID uint64 // ID of the request this is a response for 130 Slots [][]*StorageData // Lists of consecutive storage slots for the requested accounts 131 Proof [][]byte // Merkle proofs for the *last* slot range, if it's incomplete 132 } 133 134 // StorageData represents a single storage slot in a query response. 135 type StorageData struct { 136 Hash common.Hash // Hash of the storage slot 137 Body []byte // Data content of the slot 138 } 139 140 // Unpack retrieves the storage slots from the range packet and returns them in 141 // a split flat format that's more consistent with the internal data structures. 142 func (p *StorageRangesPacket) Unpack() ([][]common.Hash, [][][]byte) { 143 var ( 144 hashset = make([][]common.Hash, len(p.Slots)) 145 slotset = make([][][]byte, len(p.Slots)) 146 ) 147 for i, slots := range p.Slots { 148 hashset[i] = make([]common.Hash, len(slots)) 149 slotset[i] = make([][]byte, len(slots)) 150 for j, slot := range slots { 151 hashset[i][j] = slot.Hash 152 slotset[i][j] = slot.Body 153 } 154 } 155 return hashset, slotset 156 } 157 158 // GetByteCodesPacket represents a contract bytecode query. 159 type GetByteCodesPacket struct { 160 ID uint64 // Request ID to match up responses with 161 Hashes []common.Hash // Code hashes to retrieve the code for 162 Bytes uint64 // Soft limit at which to stop returning data 163 } 164 165 // ByteCodesPacket represents a contract bytecode query response. 166 type ByteCodesPacket struct { 167 ID uint64 // ID of the request this is a response for 168 Codes [][]byte // Requested contract bytecodes 169 } 170 171 // GetTrieNodesPacket represents a state trie node query. 172 type GetTrieNodesPacket struct { 173 ID uint64 // Request ID to match up responses with 174 Root common.Hash // Root hash of the account trie to serve 175 Paths []TrieNodePathSet // Trie node hashes to retrieve the nodes for 176 Bytes uint64 // Soft limit at which to stop returning data 177 } 178 179 // TrieNodePathSet is a list of trie node paths to retrieve. A naive way to 180 // represent trie nodes would be a simple list of `account || storage` path 181 // segments concatenated, but that would be very wasteful on the network. 182 // 183 // Instead, this array special cases the first element as the path in the 184 // account trie and the remaining elements as paths in the storage trie. To 185 // address an account node, the slice should have a length of 1 consisting 186 // of only the account path. There's no need to be able to address both an 187 // account node and a storage node in the same request as it cannot happen 188 // that a slot is accessed before the account path is fully expanded. 189 type TrieNodePathSet [][]byte 190 191 // TrieNodesPacket represents a state trie node query response. 192 type TrieNodesPacket struct { 193 ID uint64 // ID of the request this is a response for 194 Nodes [][]byte // Requested state trie nodes 195 } 196 197 func (*GetAccountRangePacket) Name() string { return "GetAccountRange" } 198 func (*GetAccountRangePacket) Kind() byte { return GetAccountRangeMsg } 199 200 func (*AccountRangePacket) Name() string { return "AccountRange" } 201 func (*AccountRangePacket) Kind() byte { return AccountRangeMsg } 202 203 func (*GetStorageRangesPacket) Name() string { return "GetStorageRanges" } 204 func (*GetStorageRangesPacket) Kind() byte { return GetStorageRangesMsg } 205 206 func (*StorageRangesPacket) Name() string { return "StorageRanges" } 207 func (*StorageRangesPacket) Kind() byte { return StorageRangesMsg } 208 209 func (*GetByteCodesPacket) Name() string { return "GetByteCodes" } 210 func (*GetByteCodesPacket) Kind() byte { return GetByteCodesMsg } 211 212 func (*ByteCodesPacket) Name() string { return "ByteCodes" } 213 func (*ByteCodesPacket) Kind() byte { return ByteCodesMsg } 214 215 func (*GetTrieNodesPacket) Name() string { return "GetTrieNodes" } 216 func (*GetTrieNodesPacket) Kind() byte { return GetTrieNodesMsg } 217 218 func (*TrieNodesPacket) Name() string { return "TrieNodes" } 219 func (*TrieNodesPacket) Kind() byte { return TrieNodesMsg }