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