github.com/c2s/go-ethereum@v1.9.7/les/protocol.go (about) 1 // Copyright 2016 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 les 18 19 import ( 20 "crypto/ecdsa" 21 "errors" 22 "fmt" 23 "io" 24 "math/big" 25 26 "github.com/ethereum/go-ethereum/common" 27 "github.com/ethereum/go-ethereum/crypto" 28 "github.com/ethereum/go-ethereum/p2p/enode" 29 "github.com/ethereum/go-ethereum/rlp" 30 ) 31 32 // Constants to match up protocol versions and messages 33 const ( 34 lpv2 = 2 35 lpv3 = 3 36 ) 37 38 // Supported versions of the les protocol (first is primary) 39 var ( 40 ClientProtocolVersions = []uint{lpv2, lpv3} 41 ServerProtocolVersions = []uint{lpv2, lpv3} 42 AdvertiseProtocolVersions = []uint{lpv2} // clients are searching for the first advertised protocol in the list 43 ) 44 45 // Number of implemented message corresponding to different protocol versions. 46 var ProtocolLengths = map[uint]uint64{lpv2: 22, lpv3: 24} 47 48 const ( 49 NetworkId = 1 50 ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message 51 ) 52 53 // les protocol message codes 54 const ( 55 // Protocol messages inherited from LPV1 56 StatusMsg = 0x00 57 AnnounceMsg = 0x01 58 GetBlockHeadersMsg = 0x02 59 BlockHeadersMsg = 0x03 60 GetBlockBodiesMsg = 0x04 61 BlockBodiesMsg = 0x05 62 GetReceiptsMsg = 0x06 63 ReceiptsMsg = 0x07 64 GetCodeMsg = 0x0a 65 CodeMsg = 0x0b 66 // Protocol messages introduced in LPV2 67 GetProofsV2Msg = 0x0f 68 ProofsV2Msg = 0x10 69 GetHelperTrieProofsMsg = 0x11 70 HelperTrieProofsMsg = 0x12 71 SendTxV2Msg = 0x13 72 GetTxStatusMsg = 0x14 73 TxStatusMsg = 0x15 74 // Protocol messages introduced in LPV3 75 StopMsg = 0x16 76 ResumeMsg = 0x17 77 ) 78 79 type requestInfo struct { 80 name string 81 maxCount uint64 82 } 83 84 var requests = map[uint64]requestInfo{ 85 GetBlockHeadersMsg: {"GetBlockHeaders", MaxHeaderFetch}, 86 GetBlockBodiesMsg: {"GetBlockBodies", MaxBodyFetch}, 87 GetReceiptsMsg: {"GetReceipts", MaxReceiptFetch}, 88 GetCodeMsg: {"GetCode", MaxCodeFetch}, 89 GetProofsV2Msg: {"GetProofsV2", MaxProofsFetch}, 90 GetHelperTrieProofsMsg: {"GetHelperTrieProofs", MaxHelperTrieProofsFetch}, 91 SendTxV2Msg: {"SendTxV2", MaxTxSend}, 92 GetTxStatusMsg: {"GetTxStatus", MaxTxStatus}, 93 } 94 95 type errCode int 96 97 const ( 98 ErrMsgTooLarge = iota 99 ErrDecode 100 ErrInvalidMsgCode 101 ErrProtocolVersionMismatch 102 ErrNetworkIdMismatch 103 ErrGenesisBlockMismatch 104 ErrNoStatusMsg 105 ErrExtraStatusMsg 106 ErrSuspendedPeer 107 ErrUselessPeer 108 ErrRequestRejected 109 ErrUnexpectedResponse 110 ErrInvalidResponse 111 ErrTooManyTimeouts 112 ErrMissingKey 113 ) 114 115 func (e errCode) String() string { 116 return errorToString[int(e)] 117 } 118 119 // XXX change once legacy code is out 120 var errorToString = map[int]string{ 121 ErrMsgTooLarge: "Message too long", 122 ErrDecode: "Invalid message", 123 ErrInvalidMsgCode: "Invalid message code", 124 ErrProtocolVersionMismatch: "Protocol version mismatch", 125 ErrNetworkIdMismatch: "NetworkId mismatch", 126 ErrGenesisBlockMismatch: "Genesis block mismatch", 127 ErrNoStatusMsg: "No status message", 128 ErrExtraStatusMsg: "Extra status message", 129 ErrSuspendedPeer: "Suspended peer", 130 ErrRequestRejected: "Request rejected", 131 ErrUnexpectedResponse: "Unexpected response", 132 ErrInvalidResponse: "Invalid response", 133 ErrTooManyTimeouts: "Too many request timeouts", 134 ErrMissingKey: "Key missing from list", 135 } 136 137 type announceBlock struct { 138 Hash common.Hash // Hash of one particular block being announced 139 Number uint64 // Number of one particular block being announced 140 Td *big.Int // Total difficulty of one particular block being announced 141 } 142 143 // announceData is the network packet for the block announcements. 144 type announceData struct { 145 Hash common.Hash // Hash of one particular block being announced 146 Number uint64 // Number of one particular block being announced 147 Td *big.Int // Total difficulty of one particular block being announced 148 ReorgDepth uint64 149 Update keyValueList 150 } 151 152 // sanityCheck verifies that the values are reasonable, as a DoS protection 153 func (a *announceData) sanityCheck() error { 154 if tdlen := a.Td.BitLen(); tdlen > 100 { 155 return fmt.Errorf("too large block TD: bitlen %d", tdlen) 156 } 157 return nil 158 } 159 160 // sign adds a signature to the block announcement by the given privKey 161 func (a *announceData) sign(privKey *ecdsa.PrivateKey) { 162 rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td}) 163 sig, _ := crypto.Sign(crypto.Keccak256(rlp), privKey) 164 a.Update = a.Update.add("sign", sig) 165 } 166 167 // checkSignature verifies if the block announcement has a valid signature by the given pubKey 168 func (a *announceData) checkSignature(id enode.ID, update keyValueMap) error { 169 var sig []byte 170 if err := update.get("sign", &sig); err != nil { 171 return err 172 } 173 rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td}) 174 recPubkey, err := crypto.SigToPub(crypto.Keccak256(rlp), sig) 175 if err != nil { 176 return err 177 } 178 if id == enode.PubkeyToIDV4(recPubkey) { 179 return nil 180 } 181 return errors.New("wrong signature") 182 } 183 184 type blockInfo struct { 185 Hash common.Hash // Hash of one particular block being announced 186 Number uint64 // Number of one particular block being announced 187 Td *big.Int // Total difficulty of one particular block being announced 188 } 189 190 // getBlockHeadersData represents a block header query. 191 type getBlockHeadersData struct { 192 Origin hashOrNumber // Block from which to retrieve headers 193 Amount uint64 // Maximum number of headers to retrieve 194 Skip uint64 // Blocks to skip between consecutive headers 195 Reverse bool // Query direction (false = rising towards latest, true = falling towards genesis) 196 } 197 198 // hashOrNumber is a combined field for specifying an origin block. 199 type hashOrNumber struct { 200 Hash common.Hash // Block hash from which to retrieve headers (excludes Number) 201 Number uint64 // Block hash from which to retrieve headers (excludes Hash) 202 } 203 204 // EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the 205 // two contained union fields. 206 func (hn *hashOrNumber) EncodeRLP(w io.Writer) error { 207 if hn.Hash == (common.Hash{}) { 208 return rlp.Encode(w, hn.Number) 209 } 210 if hn.Number != 0 { 211 return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number) 212 } 213 return rlp.Encode(w, hn.Hash) 214 } 215 216 // DecodeRLP is a specialized decoder for hashOrNumber to decode the contents 217 // into either a block hash or a block number. 218 func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error { 219 _, size, _ := s.Kind() 220 origin, err := s.Raw() 221 if err == nil { 222 switch { 223 case size == 32: 224 err = rlp.DecodeBytes(origin, &hn.Hash) 225 case size <= 8: 226 err = rlp.DecodeBytes(origin, &hn.Number) 227 default: 228 err = fmt.Errorf("invalid input size %d for origin", size) 229 } 230 } 231 return err 232 } 233 234 // CodeData is the network response packet for a node data retrieval. 235 type CodeData []struct { 236 Value []byte 237 } 238 239 type proofsData [][]rlp.RawValue