github.com/codysnider/go-ethereum@v1.10.18-0.20220420071915-14f4ae99222a/cmd/devp2p/internal/ethtest/types.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 ethtest 18 19 import ( 20 "crypto/ecdsa" 21 "fmt" 22 "time" 23 24 "github.com/ethereum/go-ethereum/eth/protocols/eth" 25 "github.com/ethereum/go-ethereum/p2p" 26 "github.com/ethereum/go-ethereum/p2p/rlpx" 27 "github.com/ethereum/go-ethereum/rlp" 28 ) 29 30 type Message interface { 31 Code() int 32 } 33 34 type Error struct { 35 err error 36 } 37 38 func (e *Error) Unwrap() error { return e.err } 39 func (e *Error) Error() string { return e.err.Error() } 40 func (e *Error) Code() int { return -1 } 41 func (e *Error) String() string { return e.Error() } 42 43 func errorf(format string, args ...interface{}) *Error { 44 return &Error{fmt.Errorf(format, args...)} 45 } 46 47 // Hello is the RLP structure of the protocol handshake. 48 type Hello struct { 49 Version uint64 50 Name string 51 Caps []p2p.Cap 52 ListenPort uint64 53 ID []byte // secp256k1 public key 54 55 // Ignore additional fields (for forward compatibility). 56 Rest []rlp.RawValue `rlp:"tail"` 57 } 58 59 func (h Hello) Code() int { return 0x00 } 60 61 // Disconnect is the RLP structure for a disconnect message. 62 type Disconnect struct { 63 Reason p2p.DiscReason 64 } 65 66 func (d Disconnect) Code() int { return 0x01 } 67 68 type Ping struct{} 69 70 func (p Ping) Code() int { return 0x02 } 71 72 type Pong struct{} 73 74 func (p Pong) Code() int { return 0x03 } 75 76 // Status is the network packet for the status message for eth/64 and later. 77 type Status eth.StatusPacket 78 79 func (s Status) Code() int { return 16 } 80 81 // NewBlockHashes is the network packet for the block announcements. 82 type NewBlockHashes eth.NewBlockHashesPacket 83 84 func (nbh NewBlockHashes) Code() int { return 17 } 85 86 type Transactions eth.TransactionsPacket 87 88 func (t Transactions) Code() int { return 18 } 89 90 // GetBlockHeaders represents a block header query. 91 type GetBlockHeaders eth.GetBlockHeadersPacket 92 93 func (g GetBlockHeaders) Code() int { return 19 } 94 95 type BlockHeaders eth.BlockHeadersPacket 96 97 func (bh BlockHeaders) Code() int { return 20 } 98 99 // GetBlockBodies represents a GetBlockBodies request 100 type GetBlockBodies eth.GetBlockBodiesPacket 101 102 func (gbb GetBlockBodies) Code() int { return 21 } 103 104 // BlockBodies is the network packet for block content distribution. 105 type BlockBodies eth.BlockBodiesPacket 106 107 func (bb BlockBodies) Code() int { return 22 } 108 109 // NewBlock is the network packet for the block propagation message. 110 type NewBlock eth.NewBlockPacket 111 112 func (nb NewBlock) Code() int { return 23 } 113 114 // NewPooledTransactionHashes is the network packet for the tx hash propagation message. 115 type NewPooledTransactionHashes eth.NewPooledTransactionHashesPacket 116 117 func (nb NewPooledTransactionHashes) Code() int { return 24 } 118 119 type GetPooledTransactions eth.GetPooledTransactionsPacket 120 121 func (gpt GetPooledTransactions) Code() int { return 25 } 122 123 type PooledTransactions eth.PooledTransactionsPacket 124 125 func (pt PooledTransactions) Code() int { return 26 } 126 127 // Conn represents an individual connection with a peer 128 type Conn struct { 129 *rlpx.Conn 130 ourKey *ecdsa.PrivateKey 131 negotiatedProtoVersion uint 132 negotiatedSnapProtoVersion uint 133 ourHighestProtoVersion uint 134 ourHighestSnapProtoVersion uint 135 caps []p2p.Cap 136 } 137 138 // Read reads an eth packet from the connection. 139 func (c *Conn) Read() Message { 140 code, rawData, _, err := c.Conn.Read() 141 if err != nil { 142 return errorf("could not read from connection: %v", err) 143 } 144 145 var msg Message 146 switch int(code) { 147 case (Hello{}).Code(): 148 msg = new(Hello) 149 case (Ping{}).Code(): 150 msg = new(Ping) 151 case (Pong{}).Code(): 152 msg = new(Pong) 153 case (Disconnect{}).Code(): 154 msg = new(Disconnect) 155 case (Status{}).Code(): 156 msg = new(Status) 157 case (GetBlockHeaders{}).Code(): 158 msg = new(GetBlockHeaders) 159 case (BlockHeaders{}).Code(): 160 msg = new(BlockHeaders) 161 case (GetBlockBodies{}).Code(): 162 msg = new(GetBlockBodies) 163 case (BlockBodies{}).Code(): 164 msg = new(BlockBodies) 165 case (NewBlock{}).Code(): 166 msg = new(NewBlock) 167 case (NewBlockHashes{}).Code(): 168 msg = new(NewBlockHashes) 169 case (Transactions{}).Code(): 170 msg = new(Transactions) 171 case (NewPooledTransactionHashes{}).Code(): 172 msg = new(NewPooledTransactionHashes) 173 case (GetPooledTransactions{}.Code()): 174 msg = new(GetPooledTransactions) 175 case (PooledTransactions{}.Code()): 176 msg = new(PooledTransactions) 177 default: 178 return errorf("invalid message code: %d", code) 179 } 180 // if message is devp2p, decode here 181 if err := rlp.DecodeBytes(rawData, msg); err != nil { 182 return errorf("could not rlp decode message: %v", err) 183 } 184 return msg 185 } 186 187 // Read66 reads an eth66 packet from the connection. 188 func (c *Conn) Read66() (uint64, Message) { 189 code, rawData, _, err := c.Conn.Read() 190 if err != nil { 191 return 0, errorf("could not read from connection: %v", err) 192 } 193 194 var msg Message 195 switch int(code) { 196 case (Hello{}).Code(): 197 msg = new(Hello) 198 case (Ping{}).Code(): 199 msg = new(Ping) 200 case (Pong{}).Code(): 201 msg = new(Pong) 202 case (Disconnect{}).Code(): 203 msg = new(Disconnect) 204 case (Status{}).Code(): 205 msg = new(Status) 206 case (GetBlockHeaders{}).Code(): 207 ethMsg := new(eth.GetBlockHeadersPacket66) 208 if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { 209 return 0, errorf("could not rlp decode message: %v", err) 210 } 211 return ethMsg.RequestId, GetBlockHeaders(*ethMsg.GetBlockHeadersPacket) 212 case (BlockHeaders{}).Code(): 213 ethMsg := new(eth.BlockHeadersPacket66) 214 if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { 215 return 0, errorf("could not rlp decode message: %v", err) 216 } 217 return ethMsg.RequestId, BlockHeaders(ethMsg.BlockHeadersPacket) 218 case (GetBlockBodies{}).Code(): 219 ethMsg := new(eth.GetBlockBodiesPacket66) 220 if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { 221 return 0, errorf("could not rlp decode message: %v", err) 222 } 223 return ethMsg.RequestId, GetBlockBodies(ethMsg.GetBlockBodiesPacket) 224 case (BlockBodies{}).Code(): 225 ethMsg := new(eth.BlockBodiesPacket66) 226 if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { 227 return 0, errorf("could not rlp decode message: %v", err) 228 } 229 return ethMsg.RequestId, BlockBodies(ethMsg.BlockBodiesPacket) 230 case (NewBlock{}).Code(): 231 msg = new(NewBlock) 232 case (NewBlockHashes{}).Code(): 233 msg = new(NewBlockHashes) 234 case (Transactions{}).Code(): 235 msg = new(Transactions) 236 case (NewPooledTransactionHashes{}).Code(): 237 msg = new(NewPooledTransactionHashes) 238 case (GetPooledTransactions{}.Code()): 239 ethMsg := new(eth.GetPooledTransactionsPacket66) 240 if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { 241 return 0, errorf("could not rlp decode message: %v", err) 242 } 243 return ethMsg.RequestId, GetPooledTransactions(ethMsg.GetPooledTransactionsPacket) 244 case (PooledTransactions{}.Code()): 245 ethMsg := new(eth.PooledTransactionsPacket66) 246 if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { 247 return 0, errorf("could not rlp decode message: %v", err) 248 } 249 return ethMsg.RequestId, PooledTransactions(ethMsg.PooledTransactionsPacket) 250 default: 251 msg = errorf("invalid message code: %d", code) 252 } 253 254 if msg != nil { 255 if err := rlp.DecodeBytes(rawData, msg); err != nil { 256 return 0, errorf("could not rlp decode message: %v", err) 257 } 258 return 0, msg 259 } 260 return 0, errorf("invalid message: %s", string(rawData)) 261 } 262 263 // Write writes a eth packet to the connection. 264 func (c *Conn) Write(msg Message) error { 265 payload, err := rlp.EncodeToBytes(msg) 266 if err != nil { 267 return err 268 } 269 _, err = c.Conn.Write(uint64(msg.Code()), payload) 270 return err 271 } 272 273 // Write66 writes an eth66 packet to the connection. 274 func (c *Conn) Write66(req eth.Packet, code int) error { 275 payload, err := rlp.EncodeToBytes(req) 276 if err != nil { 277 return err 278 } 279 _, err = c.Conn.Write(uint64(code), payload) 280 return err 281 } 282 283 // ReadSnap reads a snap/1 response with the given id from the connection. 284 func (c *Conn) ReadSnap(id uint64) (Message, error) { 285 respId := id + 1 286 start := time.Now() 287 for respId != id && time.Since(start) < timeout { 288 code, rawData, _, err := c.Conn.Read() 289 if err != nil { 290 return nil, fmt.Errorf("could not read from connection: %v", err) 291 } 292 var snpMsg interface{} 293 switch int(code) { 294 case (GetAccountRange{}).Code(): 295 snpMsg = new(GetAccountRange) 296 case (AccountRange{}).Code(): 297 snpMsg = new(AccountRange) 298 case (GetStorageRanges{}).Code(): 299 snpMsg = new(GetStorageRanges) 300 case (StorageRanges{}).Code(): 301 snpMsg = new(StorageRanges) 302 case (GetByteCodes{}).Code(): 303 snpMsg = new(GetByteCodes) 304 case (ByteCodes{}).Code(): 305 snpMsg = new(ByteCodes) 306 case (GetTrieNodes{}).Code(): 307 snpMsg = new(GetTrieNodes) 308 case (TrieNodes{}).Code(): 309 snpMsg = new(TrieNodes) 310 default: 311 //return nil, fmt.Errorf("invalid message code: %d", code) 312 continue 313 } 314 if err := rlp.DecodeBytes(rawData, snpMsg); err != nil { 315 return nil, fmt.Errorf("could not rlp decode message: %v", err) 316 } 317 return snpMsg.(Message), nil 318 319 } 320 return nil, fmt.Errorf("request timed out") 321 }