github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/neatptc/handler_test.go (about) 1 package neatptc 2 3 import ( 4 "math" 5 "math/big" 6 "math/rand" 7 "testing" 8 "time" 9 10 "github.com/neatlab/neatio/chain/consensus" 11 "github.com/neatlab/neatio/chain/core" 12 "github.com/neatlab/neatio/chain/core/rawdb" 13 "github.com/neatlab/neatio/chain/core/state" 14 "github.com/neatlab/neatio/chain/core/types" 15 "github.com/neatlab/neatio/neatptc/downloader" 16 "github.com/neatlab/neatio/network/p2p" 17 "github.com/neatlab/neatio/params" 18 "github.com/neatlab/neatio/utilities/common" 19 "github.com/neatlab/neatio/utilities/crypto" 20 ) 21 22 func TestProtocolCompatibility(t *testing.T) { 23 24 tests := []struct { 25 version uint 26 mode downloader.SyncMode 27 compatible bool 28 }{ 29 {61, downloader.FullSync, true}, {62, downloader.FullSync, true}, {63, downloader.FullSync, true}, 30 {61, downloader.FastSync, false}, {62, downloader.FastSync, false}, {63, downloader.FastSync, true}, 31 } 32 33 backup := consensus.EthProtocol.Versions 34 defer func() { consensus.EthProtocol.Versions = backup }() 35 36 for i, tt := range tests { 37 consensus.EthProtocol.Versions = []uint{tt.version} 38 39 pm, _, err := newTestProtocolManager(tt.mode, 0, nil, nil) 40 if pm != nil { 41 defer pm.Stop() 42 } 43 if (err == nil && !tt.compatible) || (err != nil && tt.compatible) { 44 t.Errorf("test %d: compatibility mismatch: have error %v, want compatibility %v", i, err, tt.compatible) 45 } 46 } 47 } 48 49 func TestGetBlockHeaders62(t *testing.T) { testGetBlockHeaders(t, 62) } 50 func TestGetBlockHeaders63(t *testing.T) { testGetBlockHeaders(t, 63) } 51 52 func testGetBlockHeaders(t *testing.T, protocol int) { 53 pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxHashFetch+15, nil, nil) 54 peer, _ := newTestPeer("peer", protocol, pm, true) 55 defer peer.close() 56 57 var unknown common.Hash 58 for i := range unknown { 59 unknown[i] = byte(i) 60 } 61 62 limit := uint64(downloader.MaxHeaderFetch) 63 tests := []struct { 64 query *getBlockHeadersData 65 expect []common.Hash 66 }{ 67 68 { 69 &getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(limit / 2).Hash()}, Amount: 1}, 70 []common.Hash{pm.blockchain.GetBlockByNumber(limit / 2).Hash()}, 71 }, { 72 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 1}, 73 []common.Hash{pm.blockchain.GetBlockByNumber(limit / 2).Hash()}, 74 }, 75 76 { 77 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3}, 78 []common.Hash{ 79 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 80 pm.blockchain.GetBlockByNumber(limit/2 + 1).Hash(), 81 pm.blockchain.GetBlockByNumber(limit/2 + 2).Hash(), 82 }, 83 }, { 84 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Amount: 3, Reverse: true}, 85 []common.Hash{ 86 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 87 pm.blockchain.GetBlockByNumber(limit/2 - 1).Hash(), 88 pm.blockchain.GetBlockByNumber(limit/2 - 2).Hash(), 89 }, 90 }, 91 92 { 93 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3}, 94 []common.Hash{ 95 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 96 pm.blockchain.GetBlockByNumber(limit/2 + 4).Hash(), 97 pm.blockchain.GetBlockByNumber(limit/2 + 8).Hash(), 98 }, 99 }, { 100 &getBlockHeadersData{Origin: hashOrNumber{Number: limit / 2}, Skip: 3, Amount: 3, Reverse: true}, 101 []common.Hash{ 102 pm.blockchain.GetBlockByNumber(limit / 2).Hash(), 103 pm.blockchain.GetBlockByNumber(limit/2 - 4).Hash(), 104 pm.blockchain.GetBlockByNumber(limit/2 - 8).Hash(), 105 }, 106 }, 107 108 { 109 &getBlockHeadersData{Origin: hashOrNumber{Number: 0}, Amount: 1}, 110 []common.Hash{pm.blockchain.GetBlockByNumber(0).Hash()}, 111 }, { 112 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64()}, Amount: 1}, 113 []common.Hash{pm.blockchain.CurrentBlock().Hash()}, 114 }, 115 116 { 117 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 1}, Amount: limit + 10, Reverse: true}, 118 pm.blockchain.GetBlockHashesFromHash(pm.blockchain.CurrentBlock().Hash(), limit), 119 }, 120 121 { 122 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 4}, Skip: 3, Amount: 3}, 123 []common.Hash{ 124 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 4).Hash(), 125 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64()).Hash(), 126 }, 127 }, { 128 &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true}, 129 []common.Hash{ 130 pm.blockchain.GetBlockByNumber(4).Hash(), 131 pm.blockchain.GetBlockByNumber(0).Hash(), 132 }, 133 }, 134 135 { 136 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 4}, Skip: 2, Amount: 3}, 137 []common.Hash{ 138 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 4).Hash(), 139 pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 1).Hash(), 140 }, 141 }, { 142 &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true}, 143 []common.Hash{ 144 pm.blockchain.GetBlockByNumber(4).Hash(), 145 pm.blockchain.GetBlockByNumber(1).Hash(), 146 }, 147 }, 148 149 { 150 &getBlockHeadersData{Origin: hashOrNumber{Number: 2}, Amount: 5, Reverse: true}, 151 []common.Hash{ 152 pm.blockchain.GetBlockByNumber(2).Hash(), 153 pm.blockchain.GetBlockByNumber(1).Hash(), 154 pm.blockchain.GetBlockByNumber(0).Hash(), 155 }, 156 }, 157 158 { 159 &getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(3).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64 - 1}, 160 []common.Hash{ 161 pm.blockchain.GetBlockByNumber(3).Hash(), 162 }, 163 }, 164 165 { 166 &getBlockHeadersData{Origin: hashOrNumber{Hash: pm.blockchain.GetBlockByNumber(1).Hash()}, Amount: 2, Reverse: false, Skip: math.MaxUint64}, 167 []common.Hash{ 168 pm.blockchain.GetBlockByNumber(1).Hash(), 169 }, 170 }, 171 172 { 173 &getBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1}, 174 []common.Hash{}, 175 }, { 176 &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() + 1}, Amount: 1}, 177 []common.Hash{}, 178 }, 179 } 180 181 for i, tt := range tests { 182 183 headers := []*types.Header{} 184 for _, hash := range tt.expect { 185 headers = append(headers, pm.blockchain.GetBlockByHash(hash).Header()) 186 } 187 188 p2p.Send(peer.app, 0x03, tt.query) 189 if err := p2p.ExpectMsg(peer.app, 0x04, headers); err != nil { 190 t.Errorf("test %d: headers mismatch: %v", i, err) 191 } 192 193 if tt.query.Origin.Hash == (common.Hash{}) { 194 if origin := pm.blockchain.GetBlockByNumber(tt.query.Origin.Number); origin != nil { 195 tt.query.Origin.Hash, tt.query.Origin.Number = origin.Hash(), 0 196 197 p2p.Send(peer.app, 0x03, tt.query) 198 if err := p2p.ExpectMsg(peer.app, 0x04, headers); err != nil { 199 t.Errorf("test %d: headers mismatch: %v", i, err) 200 } 201 } 202 } 203 } 204 } 205 206 func TestGetBlockBodies62(t *testing.T) { testGetBlockBodies(t, 62) } 207 func TestGetBlockBodies63(t *testing.T) { testGetBlockBodies(t, 63) } 208 209 func testGetBlockBodies(t *testing.T, protocol int) { 210 pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, downloader.MaxBlockFetch+15, nil, nil) 211 peer, _ := newTestPeer("peer", protocol, pm, true) 212 defer peer.close() 213 214 limit := downloader.MaxBlockFetch 215 tests := []struct { 216 random int 217 explicit []common.Hash 218 available []bool 219 expected int 220 }{ 221 {1, nil, nil, 1}, 222 {10, nil, nil, 10}, 223 {limit, nil, nil, limit}, 224 {limit + 1, nil, nil, limit}, 225 {0, []common.Hash{pm.blockchain.Genesis().Hash()}, []bool{true}, 1}, 226 {0, []common.Hash{pm.blockchain.CurrentBlock().Hash()}, []bool{true}, 1}, 227 {0, []common.Hash{{}}, []bool{false}, 0}, 228 229 {0, []common.Hash{ 230 {}, 231 pm.blockchain.GetBlockByNumber(1).Hash(), 232 {}, 233 pm.blockchain.GetBlockByNumber(10).Hash(), 234 {}, 235 pm.blockchain.GetBlockByNumber(100).Hash(), 236 {}, 237 }, []bool{false, true, false, true, false, true, false}, 3}, 238 } 239 240 for i, tt := range tests { 241 242 hashes, seen := []common.Hash{}, make(map[int64]bool) 243 bodies := []*blockBody{} 244 245 for j := 0; j < tt.random; j++ { 246 for { 247 num := rand.Int63n(int64(pm.blockchain.CurrentBlock().NumberU64())) 248 if !seen[num] { 249 seen[num] = true 250 251 block := pm.blockchain.GetBlockByNumber(uint64(num)) 252 hashes = append(hashes, block.Hash()) 253 if len(bodies) < tt.expected { 254 bodies = append(bodies, &blockBody{Transactions: block.Transactions(), Uncles: block.Uncles()}) 255 } 256 break 257 } 258 } 259 } 260 for j, hash := range tt.explicit { 261 hashes = append(hashes, hash) 262 if tt.available[j] && len(bodies) < tt.expected { 263 block := pm.blockchain.GetBlockByHash(hash) 264 bodies = append(bodies, &blockBody{Transactions: block.Transactions(), Uncles: block.Uncles()}) 265 } 266 } 267 268 p2p.Send(peer.app, 0x05, hashes) 269 if err := p2p.ExpectMsg(peer.app, 0x06, bodies); err != nil { 270 t.Errorf("test %d: bodies mismatch: %v", i, err) 271 } 272 } 273 } 274 275 func TestGetNodeData63(t *testing.T) { testGetNodeData(t, 63) } 276 277 func testGetNodeData(t *testing.T, protocol int) { 278 279 acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 280 acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 281 acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey) 282 acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey) 283 284 signer := types.HomesteadSigner{} 285 286 generator := func(i int, block *core.BlockGen) { 287 switch i { 288 case 0: 289 290 tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey) 291 block.AddTx(tx) 292 case 1: 293 294 tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey) 295 tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key) 296 block.AddTx(tx1) 297 block.AddTx(tx2) 298 case 2: 299 300 block.SetCoinbase(acc2Addr) 301 block.SetExtra([]byte("yeehaw")) 302 case 3: 303 304 b2 := block.PrevBlock(1).Header() 305 b2.Extra = []byte("foo") 306 block.AddUncle(b2) 307 b3 := block.PrevBlock(2).Header() 308 b3.Extra = []byte("foo") 309 block.AddUncle(b3) 310 } 311 } 312 313 pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, 4, generator, nil) 314 peer, _ := newTestPeer("peer", protocol, pm, true) 315 defer peer.close() 316 317 hashes := []common.Hash{} 318 319 p2p.Send(peer.app, 0x0d, hashes) 320 msg, err := peer.app.ReadMsg() 321 if err != nil { 322 t.Fatalf("failed to read node data response: %v", err) 323 } 324 if msg.Code != 0x0e { 325 t.Fatalf("response packet code mismatch: have %x, want %x", msg.Code, 0x0c) 326 } 327 var data [][]byte 328 if err := msg.Decode(&data); err != nil { 329 t.Fatalf("failed to decode response node data: %v", err) 330 } 331 332 for i, want := range hashes { 333 if hash := crypto.Keccak256Hash(data[i]); hash != want { 334 t.Errorf("data hash mismatch: have %x, want %x", hash, want) 335 } 336 } 337 statedb := rawdb.NewMemoryDatabase() 338 for i := 0; i < len(data); i++ { 339 statedb.Put(hashes[i].Bytes(), data[i]) 340 } 341 accounts := []common.Address{testBank, acc1Addr, acc2Addr} 342 for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ { 343 trie, _ := state.New(pm.blockchain.GetBlockByNumber(i).Root(), state.NewDatabase(statedb)) 344 345 for j, acc := range accounts { 346 state, _ := pm.blockchain.State() 347 bw := state.GetBalance(acc) 348 bh := trie.GetBalance(acc) 349 350 if (bw != nil && bh == nil) || (bw == nil && bh != nil) { 351 t.Errorf("test %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw) 352 } 353 if bw != nil && bh != nil && bw.Cmp(bw) != 0 { 354 t.Errorf("test %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw) 355 } 356 } 357 } 358 } 359 360 func TestGetReceipt63(t *testing.T) { testGetReceipt(t, 63) } 361 362 func testGetReceipt(t *testing.T, protocol int) { 363 364 acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 365 acc2Key, _ := crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 366 acc1Addr := crypto.PubkeyToAddress(acc1Key.PublicKey) 367 acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey) 368 369 signer := types.HomesteadSigner{} 370 371 generator := func(i int, block *core.BlockGen) { 372 switch i { 373 case 0: 374 375 tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), params.TxGas, nil, nil), signer, testBankKey) 376 block.AddTx(tx) 377 case 1: 378 379 tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, testBankKey) 380 tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), params.TxGas, nil, nil), signer, acc1Key) 381 block.AddTx(tx1) 382 block.AddTx(tx2) 383 case 2: 384 385 block.SetCoinbase(acc2Addr) 386 block.SetExtra([]byte("yeehaw")) 387 case 3: 388 389 b2 := block.PrevBlock(1).Header() 390 b2.Extra = []byte("foo") 391 block.AddUncle(b2) 392 b3 := block.PrevBlock(2).Header() 393 b3.Extra = []byte("foo") 394 block.AddUncle(b3) 395 } 396 } 397 398 pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, 4, generator, nil) 399 peer, _ := newTestPeer("peer", protocol, pm, true) 400 defer peer.close() 401 402 hashes, receipts := []common.Hash{}, []types.Receipts{} 403 for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ { 404 block := pm.blockchain.GetBlockByNumber(i) 405 406 hashes = append(hashes, block.Hash()) 407 receipts = append(receipts, pm.blockchain.GetReceiptsByHash(block.Hash())) 408 } 409 410 p2p.Send(peer.app, 0x0f, hashes) 411 if err := p2p.ExpectMsg(peer.app, 0x10, receipts); err != nil { 412 t.Errorf("receipts mismatch: %v", err) 413 } 414 } 415 416 func TestDAOChallengeNoVsNo(t *testing.T) { testDAOChallenge(t, false, false, false) } 417 func TestDAOChallengeNoVsPro(t *testing.T) { testDAOChallenge(t, false, true, false) } 418 func TestDAOChallengeProVsNo(t *testing.T) { testDAOChallenge(t, true, false, false) } 419 func TestDAOChallengeProVsPro(t *testing.T) { testDAOChallenge(t, true, true, false) } 420 func TestDAOChallengeNoVsTimeout(t *testing.T) { testDAOChallenge(t, false, false, true) } 421 func TestDAOChallengeProVsTimeout(t *testing.T) { testDAOChallenge(t, true, true, true) } 422 423 func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool) { 424 425 if timeout { 426 defer func(old time.Duration) { daoChallengeTimeout = old }(daoChallengeTimeout) 427 daoChallengeTimeout = 500 * time.Millisecond 428 } 429 430 }