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