github.com/gilgames000/kcc-geth@v1.0.6/cmd/devp2p/internal/ethtest/eth66_suite.go (about) 1 // Copyright 2021 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 "time" 21 22 "github.com/ethereum/go-ethereum/core/types" 23 "github.com/ethereum/go-ethereum/crypto" 24 "github.com/ethereum/go-ethereum/eth/protocols/eth" 25 "github.com/ethereum/go-ethereum/internal/utesting" 26 "github.com/ethereum/go-ethereum/p2p" 27 ) 28 29 // TestStatus_66 attempts to connect to the given node and exchange 30 // a status message with it on the eth66 protocol, and then check to 31 // make sure the chain head is correct. 32 func (s *Suite) TestStatus_66(t *utesting.T) { 33 conn := s.dial66(t) 34 // get protoHandshake 35 conn.handshake(t) 36 // get status 37 switch msg := conn.statusExchange66(t, s.chain).(type) { 38 case *Status: 39 status := *msg 40 if status.ProtocolVersion != uint32(66) { 41 t.Fatalf("mismatch in version: wanted 66, got %d", status.ProtocolVersion) 42 } 43 t.Logf("got status message: %s", pretty.Sdump(msg)) 44 default: 45 t.Fatalf("unexpected: %s", pretty.Sdump(msg)) 46 } 47 } 48 49 // TestGetBlockHeaders_66 tests whether the given node can respond to 50 // an eth66 `GetBlockHeaders` request and that the response is accurate. 51 func (s *Suite) TestGetBlockHeaders_66(t *utesting.T) { 52 conn := s.setupConnection66(t) 53 // get block headers 54 req := ð.GetBlockHeadersPacket66{ 55 RequestId: 3, 56 GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ 57 Origin: eth.HashOrNumber{ 58 Hash: s.chain.blocks[1].Hash(), 59 }, 60 Amount: 2, 61 Skip: 1, 62 Reverse: false, 63 }, 64 } 65 // write message 66 headers := s.getBlockHeaders66(t, conn, req, req.RequestId) 67 // check for correct headers 68 headersMatch(t, s.chain, headers) 69 } 70 71 // TestSimultaneousRequests_66 sends two simultaneous `GetBlockHeader` requests 72 // with different request IDs and checks to make sure the node responds with the correct 73 // headers per request. 74 func (s *Suite) TestSimultaneousRequests_66(t *utesting.T) { 75 // create two connections 76 conn1, conn2 := s.setupConnection66(t), s.setupConnection66(t) 77 // create two requests 78 req1 := ð.GetBlockHeadersPacket66{ 79 RequestId: 111, 80 GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ 81 Origin: eth.HashOrNumber{ 82 Hash: s.chain.blocks[1].Hash(), 83 }, 84 Amount: 2, 85 Skip: 1, 86 Reverse: false, 87 }, 88 } 89 req2 := ð.GetBlockHeadersPacket66{ 90 RequestId: 222, 91 GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ 92 Origin: eth.HashOrNumber{ 93 Hash: s.chain.blocks[1].Hash(), 94 }, 95 Amount: 4, 96 Skip: 1, 97 Reverse: false, 98 }, 99 } 100 // wait for headers for first request 101 headerChan := make(chan BlockHeaders, 1) 102 go func(headers chan BlockHeaders) { 103 headers <- s.getBlockHeaders66(t, conn1, req1, req1.RequestId) 104 }(headerChan) 105 // check headers of second request 106 headersMatch(t, s.chain, s.getBlockHeaders66(t, conn2, req2, req2.RequestId)) 107 // check headers of first request 108 headersMatch(t, s.chain, <-headerChan) 109 } 110 111 // TestBroadcast_66 tests whether a block announcement is correctly 112 // propagated to the given node's peer(s) on the eth66 protocol. 113 func (s *Suite) TestBroadcast_66(t *utesting.T) { 114 sendConn, receiveConn := s.setupConnection66(t), s.setupConnection66(t) 115 nextBlock := len(s.chain.blocks) 116 blockAnnouncement := &NewBlock{ 117 Block: s.fullChain.blocks[nextBlock], 118 TD: s.fullChain.TD(nextBlock + 1), 119 } 120 s.testAnnounce66(t, sendConn, receiveConn, blockAnnouncement) 121 // update test suite chain 122 s.chain.blocks = append(s.chain.blocks, s.fullChain.blocks[nextBlock]) 123 // wait for client to update its chain 124 if err := receiveConn.waitForBlock66(s.chain.Head()); err != nil { 125 t.Fatal(err) 126 } 127 } 128 129 // TestGetBlockBodies_66 tests whether the given node can respond to 130 // a `GetBlockBodies` request and that the response is accurate over 131 // the eth66 protocol. 132 func (s *Suite) TestGetBlockBodies_66(t *utesting.T) { 133 conn := s.setupConnection66(t) 134 // create block bodies request 135 id := uint64(55) 136 req := ð.GetBlockBodiesPacket66{ 137 RequestId: id, 138 GetBlockBodiesPacket: eth.GetBlockBodiesPacket{ 139 s.chain.blocks[54].Hash(), 140 s.chain.blocks[75].Hash(), 141 }, 142 } 143 if err := conn.write66(req, GetBlockBodies{}.Code()); err != nil { 144 t.Fatalf("could not write to connection: %v", err) 145 } 146 147 reqID, msg := conn.readAndServe66(s.chain, timeout) 148 switch msg := msg.(type) { 149 case BlockBodies: 150 if reqID != req.RequestId { 151 t.Fatalf("request ID mismatch: wanted %d, got %d", req.RequestId, reqID) 152 } 153 t.Logf("received %d block bodies", len(msg)) 154 default: 155 t.Fatalf("unexpected: %s", pretty.Sdump(msg)) 156 } 157 } 158 159 // TestLargeAnnounce_66 tests the announcement mechanism with a large block. 160 func (s *Suite) TestLargeAnnounce_66(t *utesting.T) { 161 nextBlock := len(s.chain.blocks) 162 blocks := []*NewBlock{ 163 { 164 Block: largeBlock(), 165 TD: s.fullChain.TD(nextBlock + 1), 166 }, 167 { 168 Block: s.fullChain.blocks[nextBlock], 169 TD: largeNumber(2), 170 }, 171 { 172 Block: largeBlock(), 173 TD: largeNumber(2), 174 }, 175 { 176 Block: s.fullChain.blocks[nextBlock], 177 TD: s.fullChain.TD(nextBlock + 1), 178 }, 179 } 180 181 for i, blockAnnouncement := range blocks[0:3] { 182 t.Logf("Testing malicious announcement: %v\n", i) 183 sendConn := s.setupConnection66(t) 184 if err := sendConn.Write(blockAnnouncement); err != nil { 185 t.Fatalf("could not write to connection: %v", err) 186 } 187 // Invalid announcement, check that peer disconnected 188 switch msg := sendConn.ReadAndServe(s.chain, timeout).(type) { 189 case *Disconnect: 190 case *Error: 191 break 192 default: 193 t.Fatalf("unexpected: %s wanted disconnect", pretty.Sdump(msg)) 194 } 195 } 196 // Test the last block as a valid block 197 sendConn := s.setupConnection66(t) 198 receiveConn := s.setupConnection66(t) 199 s.testAnnounce66(t, sendConn, receiveConn, blocks[3]) 200 // update test suite chain 201 s.chain.blocks = append(s.chain.blocks, s.fullChain.blocks[nextBlock]) 202 // wait for client to update its chain 203 if err := receiveConn.waitForBlock66(s.fullChain.blocks[nextBlock]); err != nil { 204 t.Fatal(err) 205 } 206 } 207 208 // TestMaliciousHandshake_66 tries to send malicious data during the handshake. 209 func (s *Suite) TestMaliciousHandshake_66(t *utesting.T) { 210 conn := s.dial66(t) 211 // write hello to client 212 pub0 := crypto.FromECDSAPub(&conn.ourKey.PublicKey)[1:] 213 handshakes := []*Hello{ 214 { 215 Version: 5, 216 Caps: []p2p.Cap{ 217 {Name: largeString(2), Version: 66}, 218 }, 219 ID: pub0, 220 }, 221 { 222 Version: 5, 223 Caps: []p2p.Cap{ 224 {Name: "eth", Version: 64}, 225 {Name: "eth", Version: 65}, 226 {Name: "eth", Version: 66}, 227 }, 228 ID: append(pub0, byte(0)), 229 }, 230 { 231 Version: 5, 232 Caps: []p2p.Cap{ 233 {Name: "eth", Version: 64}, 234 {Name: "eth", Version: 65}, 235 {Name: "eth", Version: 66}, 236 }, 237 ID: append(pub0, pub0...), 238 }, 239 { 240 Version: 5, 241 Caps: []p2p.Cap{ 242 {Name: "eth", Version: 64}, 243 {Name: "eth", Version: 65}, 244 {Name: "eth", Version: 66}, 245 }, 246 ID: largeBuffer(2), 247 }, 248 { 249 Version: 5, 250 Caps: []p2p.Cap{ 251 {Name: largeString(2), Version: 66}, 252 }, 253 ID: largeBuffer(2), 254 }, 255 } 256 for i, handshake := range handshakes { 257 t.Logf("Testing malicious handshake %v\n", i) 258 // Init the handshake 259 if err := conn.Write(handshake); err != nil { 260 t.Fatalf("could not write to connection: %v", err) 261 } 262 // check that the peer disconnected 263 timeout := 20 * time.Second 264 // Discard one hello 265 for i := 0; i < 2; i++ { 266 switch msg := conn.ReadAndServe(s.chain, timeout).(type) { 267 case *Disconnect: 268 case *Error: 269 case *Hello: 270 // Hello's are sent concurrently, so ignore them 271 continue 272 default: 273 t.Fatalf("unexpected: %s", pretty.Sdump(msg)) 274 } 275 } 276 // Dial for the next round 277 conn = s.dial66(t) 278 } 279 } 280 281 // TestMaliciousStatus_66 sends a status package with a large total difficulty. 282 func (s *Suite) TestMaliciousStatus_66(t *utesting.T) { 283 conn := s.dial66(t) 284 // get protoHandshake 285 conn.handshake(t) 286 status := &Status{ 287 ProtocolVersion: uint32(66), 288 NetworkID: s.chain.chainConfig.ChainID.Uint64(), 289 TD: largeNumber(2), 290 Head: s.chain.blocks[s.chain.Len()-1].Hash(), 291 Genesis: s.chain.blocks[0].Hash(), 292 ForkID: s.chain.ForkID(), 293 } 294 // get status 295 switch msg := conn.statusExchange(t, s.chain, status).(type) { 296 case *Status: 297 t.Logf("%+v\n", msg) 298 default: 299 t.Fatalf("expected status, got: %#v ", msg) 300 } 301 // wait for disconnect 302 switch msg := conn.ReadAndServe(s.chain, timeout).(type) { 303 case *Disconnect: 304 case *Error: 305 return 306 default: 307 t.Fatalf("expected disconnect, got: %s", pretty.Sdump(msg)) 308 } 309 } 310 311 func (s *Suite) TestTransaction_66(t *utesting.T) { 312 tests := []*types.Transaction{ 313 getNextTxFromChain(t, s), 314 unknownTx(t, s), 315 } 316 for i, tx := range tests { 317 t.Logf("Testing tx propagation: %v\n", i) 318 sendSuccessfulTx66(t, s, tx) 319 } 320 } 321 322 func (s *Suite) TestMaliciousTx_66(t *utesting.T) { 323 tests := []*types.Transaction{ 324 getOldTxFromChain(t, s), 325 invalidNonceTx(t, s), 326 hugeAmount(t, s), 327 hugeGasPrice(t, s), 328 hugeData(t, s), 329 } 330 for i, tx := range tests { 331 t.Logf("Testing malicious tx propagation: %v\n", i) 332 sendFailingTx66(t, s, tx) 333 } 334 } 335 336 // TestZeroRequestID_66 checks that a request ID of zero is still handled 337 // by the node. 338 func (s *Suite) TestZeroRequestID_66(t *utesting.T) { 339 conn := s.setupConnection66(t) 340 req := ð.GetBlockHeadersPacket66{ 341 RequestId: 0, 342 GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ 343 Origin: eth.HashOrNumber{ 344 Number: 0, 345 }, 346 Amount: 2, 347 }, 348 } 349 headersMatch(t, s.chain, s.getBlockHeaders66(t, conn, req, req.RequestId)) 350 } 351 352 // TestSameRequestID_66 sends two requests with the same request ID 353 // concurrently to a single node. 354 func (s *Suite) TestSameRequestID_66(t *utesting.T) { 355 conn := s.setupConnection66(t) 356 // create two separate requests with same ID 357 reqID := uint64(1234) 358 req1 := ð.GetBlockHeadersPacket66{ 359 RequestId: reqID, 360 GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ 361 Origin: eth.HashOrNumber{ 362 Number: 0, 363 }, 364 Amount: 2, 365 }, 366 } 367 req2 := ð.GetBlockHeadersPacket66{ 368 RequestId: reqID, 369 GetBlockHeadersPacket: ð.GetBlockHeadersPacket{ 370 Origin: eth.HashOrNumber{ 371 Number: 33, 372 }, 373 Amount: 2, 374 }, 375 } 376 // send requests concurrently 377 go func() { 378 headersMatch(t, s.chain, s.getBlockHeaders66(t, conn, req2, reqID)) 379 }() 380 // check response from first request 381 headersMatch(t, s.chain, s.getBlockHeaders66(t, conn, req1, reqID)) 382 }