github.com/klaytn/klaytn@v1.12.1/node/cn/snap/protocol.go (about) 1 // Modifications Copyright 2022 The klaytn Authors 2 // Copyright 2020 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from eth/protocols/snap/protocol.go (2022/06/29). 19 // Modified and improved for the klaytn development. 20 21 package snap 22 23 import ( 24 "errors" 25 26 "github.com/klaytn/klaytn/common" 27 ) 28 29 // Constants to match up protocol versions and messages 30 const ( 31 SNAP1 = 1 32 ) 33 34 // ProtocolName is the official short name of the `snap` protocol used during 35 // devp2p capability negotiation. 36 const ProtocolName = "snap" 37 38 // ProtocolVersions are the supported versions of the `snap` protocol (first 39 // is primary). 40 var ProtocolVersions = []uint{SNAP1} 41 42 // ProtocolLengths are the number of implemented message corresponding to 43 // different protocol versions. 44 var ProtocolLengths = map[uint]uint64{SNAP1: 8} 45 46 // maxMessageSize is the maximum cap on the size of a protocol message. 47 const maxMessageSize = 10 * 1024 * 1024 48 49 const ( 50 GetAccountRangeMsg = 0x00 51 AccountRangeMsg = 0x01 52 GetStorageRangesMsg = 0x02 53 StorageRangesMsg = 0x03 54 GetByteCodesMsg = 0x04 55 ByteCodesMsg = 0x05 56 GetTrieNodesMsg = 0x06 57 TrieNodesMsg = 0x07 58 ) 59 60 var ( 61 errMsgTooLarge = errors.New("message too long") 62 errDecode = errors.New("invalid message") 63 errInvalidMsgCode = errors.New("invalid message code") 64 errBadRequest = errors.New("bad request") 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 []byte // Account body 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) { 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 hashes[i], accounts[i] = acc.Hash, acc.Body 109 } 110 return hashes, accounts 111 } 112 113 // GetStorageRangesPacket represents an storage slot query. 114 type GetStorageRangesPacket struct { 115 ID uint64 // Request ID to match up responses with 116 Root common.Hash // Root hash of the account trie to serve 117 Accounts []common.Hash // Account hashes of the storage tries to serve 118 Origin []byte // Hash of the first storage slot to retrieve (large contract mode) 119 Limit []byte // Hash of the last storage slot to retrieve (large contract mode) 120 Bytes uint64 // Soft limit at which to stop returning data 121 } 122 123 // StorageRangesPacket represents a storage slot query response. 124 type StorageRangesPacket struct { 125 ID uint64 // ID of the request this is a response for 126 Slots [][]*StorageData // Lists of consecutive storage slots for the requested accounts 127 Proof [][]byte // Merkle proofs for the *last* slot range, if it's incomplete 128 } 129 130 // StorageData represents a single storage slot in a query response. 131 type StorageData struct { 132 Hash common.Hash // Hash of the storage slot 133 Body []byte // Data content of the slot 134 } 135 136 // Unpack retrieves the storage slots from the range packet and returns them in 137 // a split flat format that's more consistent with the internal data structures. 138 func (p *StorageRangesPacket) Unpack() ([][]common.Hash, [][][]byte) { 139 var ( 140 hashset = make([][]common.Hash, len(p.Slots)) 141 slotset = make([][][]byte, len(p.Slots)) 142 ) 143 for i, slots := range p.Slots { 144 hashset[i] = make([]common.Hash, len(slots)) 145 slotset[i] = make([][]byte, len(slots)) 146 for j, slot := range slots { 147 hashset[i][j] = slot.Hash 148 slotset[i][j] = slot.Body 149 } 150 } 151 return hashset, slotset 152 } 153 154 // GetByteCodesPacket represents a contract bytecode query. 155 type GetByteCodesPacket struct { 156 ID uint64 // Request ID to match up responses with 157 Hashes []common.Hash // Code hashes to retrieve the code for 158 Bytes uint64 // Soft limit at which to stop returning data 159 } 160 161 // ByteCodesPacket represents a contract bytecode query response. 162 type ByteCodesPacket struct { 163 ID uint64 // ID of the request this is a response for 164 Codes [][]byte // Requested contract bytecodes 165 } 166 167 // GetTrieNodesPacket represents a state trie node query. 168 type GetTrieNodesPacket struct { 169 ID uint64 // Request ID to match up responses with 170 Root common.Hash // Root hash of the account trie to serve 171 Paths []TrieNodePathSet // Trie node hashes to retrieve the nodes for 172 Bytes uint64 // Soft limit at which to stop returning data 173 } 174 175 // TrieNodePathSet is a list of trie node paths to retrieve. A naive way to 176 // represent trie nodes would be a simple list of `account || storage` path 177 // segments concatenated, but that would be very wasteful on the network. 178 // 179 // Instead, this array special cases the first element as the path in the 180 // account trie and the remaining elements as paths in the storage trie. To 181 // address an account node, the slice should have a length of 1 consisting 182 // of only the account path. There's no need to be able to address both an 183 // account node and a storage node in the same request as it cannot happen 184 // that a slot is accessed before the account path is fully expanded. 185 type TrieNodePathSet [][]byte 186 187 // TrieNodesPacket represents a state trie node query response. 188 type TrieNodesPacket struct { 189 ID uint64 // ID of the request this is a response for 190 Nodes [][]byte // Requested state trie nodes 191 } 192 193 func (*GetAccountRangePacket) Name() string { return "GetAccountRange" } 194 func (*GetAccountRangePacket) Kind() byte { return GetAccountRangeMsg } 195 196 func (*AccountRangePacket) Name() string { return "AccountRange" } 197 func (*AccountRangePacket) Kind() byte { return AccountRangeMsg } 198 199 func (*GetStorageRangesPacket) Name() string { return "GetStorageRanges" } 200 func (*GetStorageRangesPacket) Kind() byte { return GetStorageRangesMsg } 201 202 func (*StorageRangesPacket) Name() string { return "StorageRanges" } 203 func (*StorageRangesPacket) Kind() byte { return StorageRangesMsg } 204 205 func (*GetByteCodesPacket) Name() string { return "GetByteCodes" } 206 func (*GetByteCodesPacket) Kind() byte { return GetByteCodesMsg } 207 208 func (*ByteCodesPacket) Name() string { return "ByteCodes" } 209 func (*ByteCodesPacket) Kind() byte { return ByteCodesMsg } 210 211 func (*GetTrieNodesPacket) Name() string { return "GetTrieNodes" } 212 func (*GetTrieNodesPacket) Kind() byte { return GetTrieNodesMsg } 213 214 func (*TrieNodesPacket) Name() string { return "TrieNodes" } 215 func (*TrieNodesPacket) Kind() byte { return TrieNodesMsg }