github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/chain/core/blockchain_test.go (about) 1 package core 2 3 import ( 4 "fmt" 5 "math/big" 6 "math/rand" 7 "sync" 8 "testing" 9 "time" 10 11 "github.com/neatio-net/neatio/chain/consensus" 12 13 "github.com/neatio-net/neatio/chain/core/rawdb" 14 "github.com/neatio-net/neatio/chain/core/state" 15 "github.com/neatio-net/neatio/chain/core/types" 16 "github.com/neatio-net/neatio/chain/core/vm" 17 "github.com/neatio-net/neatio/neatdb" 18 "github.com/neatio-net/neatio/params" 19 "github.com/neatio-net/neatio/utilities/common" 20 "github.com/neatio-net/neatio/utilities/crypto" 21 ) 22 23 func newCanonical(engine consensus.Engine, n int, full bool) (neatdb.Database, *BlockChain, error) { 24 var ( 25 db = rawdb.NewMemoryDatabase() 26 genesis = new(Genesis).MustCommit(db) 27 ) 28 29 blockchain, _ := NewBlockChain(db, nil, params.TestChainConfig, engine, vm.Config{}, nil) 30 31 if n == 0 { 32 return db, blockchain, nil 33 } 34 if full { 35 36 blocks := makeBlockChain(genesis, n, engine, db, canonicalSeed) 37 _, err := blockchain.InsertChain(blocks) 38 return db, blockchain, err 39 } 40 41 headers := makeHeaderChain(genesis.Header(), n, engine, db, canonicalSeed) 42 _, err := blockchain.InsertHeaderChain(headers, 1) 43 return db, blockchain, err 44 } 45 46 func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) { 47 48 db, blockchain2, err := newCanonical(nil, i, full) 49 if err != nil { 50 t.Fatal("could not make new canonical in testFork", err) 51 } 52 defer blockchain2.Stop() 53 54 var hash1, hash2 common.Hash 55 if full { 56 hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash() 57 hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash() 58 } else { 59 hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash() 60 hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash() 61 } 62 if hash1 != hash2 { 63 t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) 64 } 65 66 var ( 67 blockChainB []*types.Block 68 headerChainB []*types.Header 69 ) 70 if full { 71 blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, nil, db, forkSeed) 72 if _, err := blockchain2.InsertChain(blockChainB); err != nil { 73 t.Fatalf("failed to insert forking chain: %v", err) 74 } 75 } else { 76 headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, nil, db, forkSeed) 77 if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil { 78 t.Fatalf("failed to insert forking chain: %v", err) 79 } 80 } 81 82 var tdPre, tdPost *big.Int 83 84 if full { 85 tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()) 86 if err := testBlockChainImport(blockChainB, blockchain); err != nil { 87 t.Fatalf("failed to import forked block chain: %v", err) 88 } 89 tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash()) 90 } else { 91 tdPre = blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()) 92 if err := testHeaderChainImport(headerChainB, blockchain); err != nil { 93 t.Fatalf("failed to import forked header chain: %v", err) 94 } 95 tdPost = blockchain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash()) 96 } 97 98 comparator(tdPre, tdPost) 99 } 100 101 func printChain(bc *BlockChain) { 102 for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- { 103 b := bc.GetBlockByNumber(uint64(i)) 104 fmt.Printf("\t%x %v\n", b.Hash(), b.Difficulty()) 105 } 106 } 107 108 func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { 109 for _, block := range chain { 110 111 err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) 112 if err == nil { 113 err = blockchain.validator.ValidateBody(block) 114 } 115 if err != nil { 116 if err == ErrKnownBlock { 117 continue 118 } 119 return err 120 } 121 statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache) 122 if err != nil { 123 return err 124 } 125 receipts, _, usedGas, _, err := blockchain.Processor().Process(block, statedb, vm.Config{}) 126 if err != nil { 127 blockchain.reportBlock(block, receipts, err) 128 return err 129 } 130 err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas) 131 if err != nil { 132 blockchain.reportBlock(block, receipts, err) 133 return err 134 } 135 blockchain.chainmu.Lock() 136 rawdb.WriteTd(blockchain.db, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash()))) 137 rawdb.WriteBlock(blockchain.db, block) 138 statedb.Commit(false) 139 blockchain.chainmu.Unlock() 140 } 141 return nil 142 } 143 144 func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { 145 for _, header := range chain { 146 147 if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil { 148 return err 149 } 150 151 blockchain.chainmu.Lock() 152 rawdb.WriteTd(blockchain.db, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash))) 153 rawdb.WriteHeader(blockchain.db, header) 154 blockchain.chainmu.Unlock() 155 } 156 return nil 157 } 158 159 func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *testing.T) { 160 _, err := blockchain.InsertChain(chain) 161 if err != nil { 162 fmt.Println(err) 163 t.FailNow() 164 } 165 done <- true 166 } 167 168 func TestLastBlock(t *testing.T) { 169 _, blockchain, err := newCanonical(nil, 0, true) 170 if err != nil { 171 t.Fatalf("failed to create pristine chain: %v", err) 172 } 173 defer blockchain.Stop() 174 175 blocks := makeBlockChain(blockchain.CurrentBlock(), 1, nil, blockchain.db, 0) 176 if _, err := blockchain.InsertChain(blocks); err != nil { 177 t.Fatalf("Failed to insert block: %v", err) 178 } 179 if blocks[len(blocks)-1].Hash() != rawdb.ReadHeadBlockHash(blockchain.db) { 180 t.Fatalf("Write/Get HeadBlockHash failed") 181 } 182 } 183 184 func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) } 185 func TestExtendCanonicalBlocks(t *testing.T) { testExtendCanonical(t, true) } 186 187 func testExtendCanonical(t *testing.T, full bool) { 188 length := 5 189 190 _, processor, err := newCanonical(nil, length, full) 191 if err != nil { 192 t.Fatalf("failed to make new canonical chain: %v", err) 193 } 194 defer processor.Stop() 195 196 better := func(td1, td2 *big.Int) { 197 if td2.Cmp(td1) <= 0 { 198 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 199 } 200 } 201 202 testFork(t, processor, length, 1, full, better) 203 testFork(t, processor, length, 2, full, better) 204 testFork(t, processor, length, 5, full, better) 205 testFork(t, processor, length, 10, full, better) 206 } 207 208 func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) } 209 func TestShorterForkBlocks(t *testing.T) { testShorterFork(t, true) } 210 211 func testShorterFork(t *testing.T, full bool) { 212 length := 10 213 214 _, processor, err := newCanonical(nil, length, full) 215 if err != nil { 216 t.Fatalf("failed to make new canonical chain: %v", err) 217 } 218 defer processor.Stop() 219 220 worse := func(td1, td2 *big.Int) { 221 if td2.Cmp(td1) >= 0 { 222 t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) 223 } 224 } 225 226 testFork(t, processor, 0, 3, full, worse) 227 testFork(t, processor, 0, 7, full, worse) 228 testFork(t, processor, 1, 1, full, worse) 229 testFork(t, processor, 1, 7, full, worse) 230 testFork(t, processor, 5, 3, full, worse) 231 testFork(t, processor, 5, 4, full, worse) 232 } 233 234 func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) } 235 func TestLongerForkBlocks(t *testing.T) { testLongerFork(t, true) } 236 237 func testLongerFork(t *testing.T, full bool) { 238 length := 10 239 240 _, processor, err := newCanonical(nil, length, full) 241 if err != nil { 242 t.Fatalf("failed to make new canonical chain: %v", err) 243 } 244 defer processor.Stop() 245 246 better := func(td1, td2 *big.Int) { 247 if td2.Cmp(td1) <= 0 { 248 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 249 } 250 } 251 252 testFork(t, processor, 0, 11, full, better) 253 testFork(t, processor, 0, 15, full, better) 254 testFork(t, processor, 1, 10, full, better) 255 testFork(t, processor, 1, 12, full, better) 256 testFork(t, processor, 5, 6, full, better) 257 testFork(t, processor, 5, 8, full, better) 258 } 259 260 func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) } 261 func TestEqualForkBlocks(t *testing.T) { testEqualFork(t, true) } 262 263 func testEqualFork(t *testing.T, full bool) { 264 length := 10 265 266 _, processor, err := newCanonical(nil, length, full) 267 if err != nil { 268 t.Fatalf("failed to make new canonical chain: %v", err) 269 } 270 defer processor.Stop() 271 272 equal := func(td1, td2 *big.Int) { 273 if td2.Cmp(td1) != 0 { 274 t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) 275 } 276 } 277 278 testFork(t, processor, 0, 10, full, equal) 279 testFork(t, processor, 1, 9, full, equal) 280 testFork(t, processor, 2, 8, full, equal) 281 testFork(t, processor, 5, 5, full, equal) 282 testFork(t, processor, 6, 4, full, equal) 283 testFork(t, processor, 9, 1, full, equal) 284 } 285 286 func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) } 287 func TestBrokenBlockChain(t *testing.T) { testBrokenChain(t, true) } 288 289 func testBrokenChain(t *testing.T, full bool) { 290 291 db, blockchain, err := newCanonical(nil, 10, full) 292 if err != nil { 293 t.Fatalf("failed to make new canonical chain: %v", err) 294 } 295 defer blockchain.Stop() 296 297 if full { 298 chain := makeBlockChain(blockchain.CurrentBlock(), 5, nil, db, forkSeed)[1:] 299 if err := testBlockChainImport(chain, blockchain); err == nil { 300 t.Errorf("broken block chain not reported") 301 } 302 } else { 303 chain := makeHeaderChain(blockchain.CurrentHeader(), 5, nil, db, forkSeed)[1:] 304 if err := testHeaderChainImport(chain, blockchain); err == nil { 305 t.Errorf("broken header chain not reported") 306 } 307 } 308 } 309 310 func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) } 311 func TestReorgLongBlocks(t *testing.T) { testReorgLong(t, true) } 312 313 func testReorgLong(t *testing.T, full bool) { 314 testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280, full) 315 } 316 317 func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false) } 318 func TestReorgShortBlocks(t *testing.T) { testReorgShort(t, true) } 319 320 func testReorgShort(t *testing.T, full bool) { 321 322 easy := make([]int64, 96) 323 for i := 0; i < len(easy); i++ { 324 easy[i] = 60 325 } 326 diff := make([]int64, len(easy)-1) 327 for i := 0; i < len(diff); i++ { 328 diff[i] = -9 329 } 330 testReorg(t, easy, diff, 12615120, full) 331 } 332 333 func testReorg(t *testing.T, first, second []int64, td int64, full bool) { 334 335 db, blockchain, err := newCanonical(nil, 0, full) 336 if err != nil { 337 t.Fatalf("failed to create pristine chain: %v", err) 338 } 339 defer blockchain.Stop() 340 341 easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), nil, db, len(first), func(i int, b *BlockGen) { 342 b.OffsetTime(first[i]) 343 }) 344 diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), nil, db, len(second), func(i int, b *BlockGen) { 345 b.OffsetTime(second[i]) 346 }) 347 if full { 348 if _, err := blockchain.InsertChain(easyBlocks); err != nil { 349 t.Fatalf("failed to insert easy chain: %v", err) 350 } 351 if _, err := blockchain.InsertChain(diffBlocks); err != nil { 352 t.Fatalf("failed to insert difficult chain: %v", err) 353 } 354 } else { 355 easyHeaders := make([]*types.Header, len(easyBlocks)) 356 for i, block := range easyBlocks { 357 easyHeaders[i] = block.Header() 358 } 359 diffHeaders := make([]*types.Header, len(diffBlocks)) 360 for i, block := range diffBlocks { 361 diffHeaders[i] = block.Header() 362 } 363 if _, err := blockchain.InsertHeaderChain(easyHeaders, 1); err != nil { 364 t.Fatalf("failed to insert easy chain: %v", err) 365 } 366 if _, err := blockchain.InsertHeaderChain(diffHeaders, 1); err != nil { 367 t.Fatalf("failed to insert difficult chain: %v", err) 368 } 369 } 370 371 if full { 372 prev := blockchain.CurrentBlock() 373 for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, blockchain.GetBlockByNumber(block.NumberU64()-1) { 374 if prev.ParentHash() != block.Hash() { 375 t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash(), block.Hash()) 376 } 377 } 378 } else { 379 prev := blockchain.CurrentHeader() 380 for header := blockchain.GetHeaderByNumber(blockchain.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, blockchain.GetHeaderByNumber(header.Number.Uint64()-1) { 381 if prev.ParentHash != header.Hash() { 382 t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash()) 383 } 384 } 385 } 386 387 want := new(big.Int).Add(blockchain.genesisBlock.Difficulty(), big.NewInt(td)) 388 if full { 389 if have := blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()); have.Cmp(want) != 0 { 390 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 391 } 392 } else { 393 if have := blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()); have.Cmp(want) != 0 { 394 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 395 } 396 } 397 } 398 399 func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) } 400 func TestBadBlockHashes(t *testing.T) { testBadHashes(t, true) } 401 402 func testBadHashes(t *testing.T, full bool) { 403 404 db, blockchain, err := newCanonical(nil, 0, full) 405 if err != nil { 406 t.Fatalf("failed to create pristine chain: %v", err) 407 } 408 defer blockchain.Stop() 409 410 if full { 411 blocks := makeBlockChain(blockchain.CurrentBlock(), 3, nil, db, 10) 412 413 BadHashes[blocks[2].Header().Hash()] = true 414 defer func() { delete(BadHashes, blocks[2].Header().Hash()) }() 415 416 _, err = blockchain.InsertChain(blocks) 417 } else { 418 headers := makeHeaderChain(blockchain.CurrentHeader(), 3, nil, db, 10) 419 420 BadHashes[headers[2].Hash()] = true 421 defer func() { delete(BadHashes, headers[2].Hash()) }() 422 423 _, err = blockchain.InsertHeaderChain(headers, 1) 424 } 425 if err != ErrBlacklistedHash { 426 t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash) 427 } 428 } 429 430 func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) } 431 func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) } 432 433 func testReorgBadHashes(t *testing.T, full bool) { 434 435 db, blockchain, err := newCanonical(nil, 0, full) 436 if err != nil { 437 t.Fatalf("failed to create pristine chain: %v", err) 438 } 439 440 headers := makeHeaderChain(blockchain.CurrentHeader(), 4, nil, db, 10) 441 blocks := makeBlockChain(blockchain.CurrentBlock(), 4, nil, db, 10) 442 443 if full { 444 if _, err = blockchain.InsertChain(blocks); err != nil { 445 t.Errorf("failed to import blocks: %v", err) 446 } 447 if blockchain.CurrentBlock().Hash() != blocks[3].Hash() { 448 t.Errorf("last block hash mismatch: have: %x, want %x", blockchain.CurrentBlock().Hash(), blocks[3].Header().Hash()) 449 } 450 BadHashes[blocks[3].Header().Hash()] = true 451 defer func() { delete(BadHashes, blocks[3].Header().Hash()) }() 452 } else { 453 if _, err = blockchain.InsertHeaderChain(headers, 1); err != nil { 454 t.Errorf("failed to import headers: %v", err) 455 } 456 if blockchain.CurrentHeader().Hash() != headers[3].Hash() { 457 t.Errorf("last header hash mismatch: have: %x, want %x", blockchain.CurrentHeader().Hash(), headers[3].Hash()) 458 } 459 BadHashes[headers[3].Hash()] = true 460 defer func() { delete(BadHashes, headers[3].Hash()) }() 461 } 462 blockchain.Stop() 463 464 ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, nil, vm.Config{}, nil) 465 if err != nil { 466 t.Fatalf("failed to create new chain manager: %v", err) 467 } 468 if full { 469 if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() { 470 t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash()) 471 } 472 if blocks[2].Header().GasLimit != ncm.GasLimit() { 473 t.Errorf("last block gasLimit mismatch: have: %d, want %d", ncm.GasLimit(), blocks[2].Header().GasLimit) 474 } 475 } else { 476 if ncm.CurrentHeader().Hash() != headers[2].Hash() { 477 t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) 478 } 479 } 480 ncm.Stop() 481 } 482 483 func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) } 484 func TestBlocksInsertNonceError(t *testing.T) { testInsertNonceError(t, true) } 485 486 func testInsertNonceError(t *testing.T, full bool) { 487 for i := 1; i < 25 && !t.Failed(); i++ { 488 489 db, blockchain, err := newCanonical(nil, 0, full) 490 if err != nil { 491 t.Fatalf("failed to create pristine chain: %v", err) 492 } 493 defer blockchain.Stop() 494 495 var ( 496 failAt int 497 failRes int 498 failNum uint64 499 ) 500 if full { 501 blocks := makeBlockChain(blockchain.CurrentBlock(), i, nil, db, 0) 502 503 failAt = rand.Int() % len(blocks) 504 failNum = blocks[failAt].NumberU64() 505 506 failRes, err = blockchain.InsertChain(blocks) 507 } else { 508 headers := makeHeaderChain(blockchain.CurrentHeader(), i, nil, db, 0) 509 510 failAt = rand.Int() % len(headers) 511 failNum = headers[failAt].Number.Uint64() 512 513 blockchain.hc.engine = blockchain.engine 514 failRes, err = blockchain.InsertHeaderChain(headers, 1) 515 } 516 517 if failRes != failAt { 518 t.Errorf("test %d: failure index mismatch: have %d, want %d", i, failRes, failAt) 519 } 520 521 for j := 0; j < i-failAt; j++ { 522 if full { 523 if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil { 524 t.Errorf("test %d: invalid block in chain: %v", i, block) 525 } 526 } else { 527 if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil { 528 t.Errorf("test %d: invalid header in chain: %v", i, header) 529 } 530 } 531 } 532 } 533 } 534 535 func TestFastVsFullChains(t *testing.T) { 536 537 var ( 538 gendb = rawdb.NewMemoryDatabase() 539 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 540 address = crypto.PubkeyToAddress(key.PublicKey) 541 funds = big.NewInt(1000000000) 542 gspec = &Genesis{ 543 Config: params.TestChainConfig, 544 Alloc: GenesisAlloc{address: {Balance: funds}}, 545 } 546 genesis = gspec.MustCommit(gendb) 547 signer = types.NewEIP155Signer(gspec.Config.ChainId) 548 ) 549 blocks, receipts := GenerateChain(gspec.Config, genesis, nil, gendb, 1024, func(i int, block *BlockGen) { 550 block.SetCoinbase(common.Address{0x00}) 551 552 if i%3 == 2 { 553 for j := 0; j < i%4+1; j++ { 554 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key) 555 if err != nil { 556 panic(err) 557 } 558 block.AddTx(tx) 559 } 560 } 561 562 if i%5 == 5 { 563 block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))}) 564 } 565 }) 566 567 archiveDb := rawdb.NewMemoryDatabase() 568 gspec.MustCommit(archiveDb) 569 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, nil, vm.Config{}, nil) 570 defer archive.Stop() 571 572 if n, err := archive.InsertChain(blocks); err != nil { 573 t.Fatalf("failed to process block %d: %v", n, err) 574 } 575 576 fastDb := rawdb.NewMemoryDatabase() 577 gspec.MustCommit(fastDb) 578 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, nil, vm.Config{}, nil) 579 defer fast.Stop() 580 581 headers := make([]*types.Header, len(blocks)) 582 for i, block := range blocks { 583 headers[i] = block.Header() 584 } 585 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 586 t.Fatalf("failed to insert header %d: %v", n, err) 587 } 588 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 589 t.Fatalf("failed to insert receipt %d: %v", n, err) 590 } 591 592 for i := 0; i < len(blocks); i++ { 593 num, hash := blocks[i].NumberU64(), blocks[i].Hash() 594 595 if ftd, atd := fast.GetTdByHash(hash), archive.GetTdByHash(hash); ftd.Cmp(atd) != 0 { 596 t.Errorf("block #%d [%x]: td mismatch: have %v, want %v", num, hash, ftd, atd) 597 } 598 if fheader, aheader := fast.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); fheader.Hash() != aheader.Hash() { 599 t.Errorf("block #%d [%x]: header mismatch: have %v, want %v", num, hash, fheader, aheader) 600 } 601 if fblock, ablock := fast.GetBlockByHash(hash), archive.GetBlockByHash(hash); fblock.Hash() != ablock.Hash() { 602 t.Errorf("block #%d [%x]: block mismatch: have %v, want %v", num, hash, fblock, ablock) 603 } else if types.DeriveSha(fblock.Transactions()) != types.DeriveSha(ablock.Transactions()) { 604 t.Errorf("block #%d [%x]: transactions mismatch: have %v, want %v", num, hash, fblock.Transactions(), ablock.Transactions()) 605 } else if types.CalcUncleHash(fblock.Uncles()) != types.CalcUncleHash(ablock.Uncles()) { 606 t.Errorf("block #%d [%x]: uncles mismatch: have %v, want %v", num, hash, fblock.Uncles(), ablock.Uncles()) 607 } 608 if freceipts, areceipts := rawdb.ReadReceipts(fastDb, hash, *rawdb.ReadHeaderNumber(fastDb, hash)), rawdb.ReadReceipts(archiveDb, hash, *rawdb.ReadHeaderNumber(archiveDb, hash)); types.DeriveSha(freceipts) != types.DeriveSha(areceipts) { 609 t.Errorf("block #%d [%x]: receipts mismatch: have %v, want %v", num, hash, freceipts, areceipts) 610 } 611 } 612 613 for i := 0; i < len(blocks)+1; i++ { 614 if fhash, ahash := rawdb.ReadCanonicalHash(fastDb, uint64(i)), rawdb.ReadCanonicalHash(archiveDb, uint64(i)); fhash != ahash { 615 t.Errorf("block #%d: canonical hash mismatch: have %v, want %v", i, fhash, ahash) 616 } 617 } 618 } 619 620 func TestLightVsFastVsFullChainHeads(t *testing.T) { 621 622 var ( 623 gendb = rawdb.NewMemoryDatabase() 624 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 625 address = crypto.PubkeyToAddress(key.PublicKey) 626 funds = big.NewInt(1000000000) 627 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 628 genesis = gspec.MustCommit(gendb) 629 ) 630 height := uint64(1024) 631 blocks, receipts := GenerateChain(gspec.Config, genesis, nil, gendb, int(height), nil) 632 633 remove := []common.Hash{} 634 for _, block := range blocks[height/2:] { 635 remove = append(remove, block.Hash()) 636 } 637 638 assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { 639 if num := chain.CurrentBlock().NumberU64(); num != block { 640 t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) 641 } 642 if num := chain.CurrentFastBlock().NumberU64(); num != fast { 643 t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast) 644 } 645 if num := chain.CurrentHeader().Number.Uint64(); num != header { 646 t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header) 647 } 648 } 649 650 archiveDb := rawdb.NewMemoryDatabase() 651 gspec.MustCommit(archiveDb) 652 653 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, nil, vm.Config{}, nil) 654 if n, err := archive.InsertChain(blocks); err != nil { 655 t.Fatalf("failed to process block %d: %v", n, err) 656 } 657 defer archive.Stop() 658 659 assert(t, "archive", archive, height, height, height) 660 archive.Rollback(remove) 661 assert(t, "archive", archive, height/2, height/2, height/2) 662 663 fastDb := rawdb.NewMemoryDatabase() 664 gspec.MustCommit(fastDb) 665 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, nil, vm.Config{}, nil) 666 defer fast.Stop() 667 668 headers := make([]*types.Header, len(blocks)) 669 for i, block := range blocks { 670 headers[i] = block.Header() 671 } 672 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 673 t.Fatalf("failed to insert header %d: %v", n, err) 674 } 675 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 676 t.Fatalf("failed to insert receipt %d: %v", n, err) 677 } 678 assert(t, "fast", fast, height, height, 0) 679 fast.Rollback(remove) 680 assert(t, "fast", fast, height/2, height/2, 0) 681 682 lightDb := rawdb.NewMemoryDatabase() 683 gspec.MustCommit(lightDb) 684 685 light, _ := NewBlockChain(lightDb, nil, gspec.Config, nil, vm.Config{}, nil) 686 if n, err := light.InsertHeaderChain(headers, 1); err != nil { 687 t.Fatalf("failed to insert header %d: %v", n, err) 688 } 689 defer light.Stop() 690 691 assert(t, "light", light, height, 0, 0) 692 light.Rollback(remove) 693 assert(t, "light", light, height/2, 0, 0) 694 } 695 696 func TestChainTxReorgs(t *testing.T) { 697 var ( 698 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 699 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 700 key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 701 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 702 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 703 addr3 = crypto.PubkeyToAddress(key3.PublicKey) 704 db = rawdb.NewMemoryDatabase() 705 gspec = &Genesis{ 706 Config: params.TestChainConfig, 707 GasLimit: 3141592, 708 Alloc: GenesisAlloc{ 709 addr1: {Balance: big.NewInt(1000000)}, 710 addr2: {Balance: big.NewInt(1000000)}, 711 addr3: {Balance: big.NewInt(1000000)}, 712 }, 713 } 714 genesis = gspec.MustCommit(db) 715 signer = types.NewEIP155Signer(gspec.Config.ChainId) 716 ) 717 718 postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 719 swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 720 721 var pastDrop, freshDrop *types.Transaction 722 723 var pastAdd, freshAdd, futureAdd *types.Transaction 724 725 chain, _ := GenerateChain(gspec.Config, genesis, nil, db, 3, func(i int, gen *BlockGen) { 726 switch i { 727 case 0: 728 pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 729 730 gen.AddTx(pastDrop) 731 gen.AddTx(postponed) 732 733 case 2: 734 freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 735 736 gen.AddTx(freshDrop) 737 gen.AddTx(swapped) 738 739 gen.OffsetTime(9) 740 } 741 }) 742 743 blockchain, _ := NewBlockChain(db, nil, gspec.Config, nil, vm.Config{}, nil) 744 if i, err := blockchain.InsertChain(chain); err != nil { 745 t.Fatalf("failed to insert original chain[%d]: %v", i, err) 746 } 747 defer blockchain.Stop() 748 749 chain, _ = GenerateChain(gspec.Config, genesis, nil, db, 5, func(i int, gen *BlockGen) { 750 switch i { 751 case 0: 752 pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 753 gen.AddTx(pastAdd) 754 755 case 2: 756 gen.AddTx(postponed) 757 gen.AddTx(swapped) 758 759 freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 760 gen.AddTx(freshAdd) 761 762 case 3: 763 futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 764 gen.AddTx(futureAdd) 765 } 766 }) 767 if _, err := blockchain.InsertChain(chain); err != nil { 768 t.Fatalf("failed to insert forked chain: %v", err) 769 } 770 771 for i, tx := range (types.Transactions{pastDrop, freshDrop}) { 772 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn != nil { 773 t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) 774 } 775 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt != nil { 776 t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt) 777 } 778 } 779 780 for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) { 781 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 782 t.Errorf("add %d: expected tx to be found", i) 783 } 784 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt == nil { 785 t.Errorf("add %d: expected receipt to be found", i) 786 } 787 } 788 789 for i, tx := range (types.Transactions{postponed, swapped}) { 790 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 791 t.Errorf("share %d: expected tx to be found", i) 792 } 793 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt == nil { 794 t.Errorf("share %d: expected receipt to be found", i) 795 } 796 } 797 } 798 799 func TestLogReorgs(t *testing.T) { 800 801 var ( 802 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 803 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 804 db = rawdb.NewMemoryDatabase() 805 806 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 807 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 808 genesis = gspec.MustCommit(db) 809 signer = types.NewEIP155Signer(gspec.Config.ChainId) 810 ) 811 812 blockchain, _ := NewBlockChain(db, nil, gspec.Config, nil, vm.Config{}, nil) 813 defer blockchain.Stop() 814 815 rmLogsCh := make(chan RemovedLogsEvent) 816 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 817 chain, _ := GenerateChain(params.TestChainConfig, genesis, nil, db, 2, func(i int, gen *BlockGen) { 818 if i == 1 { 819 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 820 if err != nil { 821 t.Fatalf("failed to create tx: %v", err) 822 } 823 gen.AddTx(tx) 824 } 825 }) 826 if _, err := blockchain.InsertChain(chain); err != nil { 827 t.Fatalf("failed to insert chain: %v", err) 828 } 829 830 chain, _ = GenerateChain(params.TestChainConfig, genesis, nil, db, 3, func(i int, gen *BlockGen) {}) 831 if _, err := blockchain.InsertChain(chain); err != nil { 832 t.Fatalf("failed to insert forked chain: %v", err) 833 } 834 835 timeout := time.NewTimer(1 * time.Second) 836 select { 837 case ev := <-rmLogsCh: 838 if len(ev.Logs) == 0 { 839 t.Error("expected logs") 840 } 841 case <-timeout.C: 842 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 843 } 844 } 845 846 func TestReorgSideEvent(t *testing.T) { 847 var ( 848 db = rawdb.NewMemoryDatabase() 849 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 850 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 851 gspec = &Genesis{ 852 Config: params.TestChainConfig, 853 Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}, 854 } 855 genesis = gspec.MustCommit(db) 856 signer = types.NewEIP155Signer(gspec.Config.ChainId) 857 ) 858 859 blockchain, _ := NewBlockChain(db, nil, gspec.Config, nil, vm.Config{}, nil) 860 defer blockchain.Stop() 861 862 chain, _ := GenerateChain(gspec.Config, genesis, nil, db, 3, func(i int, gen *BlockGen) {}) 863 if _, err := blockchain.InsertChain(chain); err != nil { 864 t.Fatalf("failed to insert chain: %v", err) 865 } 866 867 replacementBlocks, _ := GenerateChain(gspec.Config, genesis, nil, db, 4, func(i int, gen *BlockGen) { 868 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), nil), signer, key1) 869 if i == 2 { 870 gen.OffsetTime(-9) 871 } 872 if err != nil { 873 t.Fatalf("failed to create tx: %v", err) 874 } 875 gen.AddTx(tx) 876 }) 877 chainSideCh := make(chan ChainSideEvent, 64) 878 blockchain.SubscribeChainSideEvent(chainSideCh) 879 if _, err := blockchain.InsertChain(replacementBlocks); err != nil { 880 t.Fatalf("failed to insert chain: %v", err) 881 } 882 883 expectedSideHashes := map[common.Hash]bool{ 884 replacementBlocks[0].Hash(): true, 885 replacementBlocks[1].Hash(): true, 886 chain[0].Hash(): true, 887 chain[1].Hash(): true, 888 chain[2].Hash(): true, 889 } 890 891 i := 0 892 893 const timeoutDura = 10 * time.Second 894 timeout := time.NewTimer(timeoutDura) 895 done: 896 for { 897 select { 898 case ev := <-chainSideCh: 899 block := ev.Block 900 if _, ok := expectedSideHashes[block.Hash()]; !ok { 901 t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash()) 902 } 903 i++ 904 905 if i == len(expectedSideHashes) { 906 timeout.Stop() 907 908 break done 909 } 910 timeout.Reset(timeoutDura) 911 912 case <-timeout.C: 913 t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent") 914 } 915 } 916 917 select { 918 case e := <-chainSideCh: 919 t.Errorf("unexpected event fired: %v", e) 920 case <-time.After(250 * time.Millisecond): 921 } 922 923 } 924 925 func TestCanonicalBlockRetrieval(t *testing.T) { 926 _, blockchain, err := newCanonical(nil, 0, true) 927 if err != nil { 928 t.Fatalf("failed to create pristine chain: %v", err) 929 } 930 defer blockchain.Stop() 931 932 chain, _ := GenerateChain(blockchain.chainConfig, blockchain.genesisBlock, nil, blockchain.db, 10, func(i int, gen *BlockGen) {}) 933 934 var pend sync.WaitGroup 935 pend.Add(len(chain)) 936 937 for i := range chain { 938 go func(block *types.Block) { 939 defer pend.Done() 940 941 for { 942 ch := rawdb.ReadCanonicalHash(blockchain.db, block.NumberU64()) 943 if ch == (common.Hash{}) { 944 continue 945 } 946 if ch != block.Hash() { 947 t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex()) 948 } 949 fb := rawdb.ReadBlock(blockchain.db, ch, block.NumberU64()) 950 if fb == nil { 951 t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex()) 952 } 953 if fb.Hash() != block.Hash() { 954 t.Fatalf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex()) 955 } 956 return 957 } 958 }(chain[i]) 959 960 if _, err := blockchain.InsertChain(types.Blocks{chain[i]}); err != nil { 961 t.Fatalf("failed to insert block %d: %v", i, err) 962 } 963 } 964 pend.Wait() 965 } 966 967 func TestEIP155Transition(t *testing.T) { 968 969 var ( 970 db = rawdb.NewMemoryDatabase() 971 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 972 address = crypto.PubkeyToAddress(key.PublicKey) 973 funds = big.NewInt(1000000000) 974 deleteAddr = common.Address{1} 975 gspec = &Genesis{ 976 Config: ¶ms.ChainConfig{ChainId: big.NewInt(1), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}, 977 Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, 978 } 979 genesis = gspec.MustCommit(db) 980 ) 981 982 blockchain, _ := NewBlockChain(db, nil, gspec.Config, nil, vm.Config{}, nil) 983 defer blockchain.Stop() 984 985 blocks, _ := GenerateChain(gspec.Config, genesis, nil, db, 4, func(i int, block *BlockGen) { 986 var ( 987 tx *types.Transaction 988 err error 989 basicTx = func(signer types.Signer) (*types.Transaction, error) { 990 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 100000, new(big.Int), nil), signer, key) 991 } 992 ) 993 switch i { 994 case 0: 995 tx, err = basicTx(types.HomesteadSigner{}) 996 if err != nil { 997 t.Fatal(err) 998 } 999 block.AddTx(tx) 1000 case 2: 1001 tx, err = basicTx(types.HomesteadSigner{}) 1002 if err != nil { 1003 t.Fatal(err) 1004 } 1005 block.AddTx(tx) 1006 1007 tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainId)) 1008 if err != nil { 1009 t.Fatal(err) 1010 } 1011 block.AddTx(tx) 1012 case 3: 1013 tx, err = basicTx(types.HomesteadSigner{}) 1014 if err != nil { 1015 t.Fatal(err) 1016 } 1017 block.AddTx(tx) 1018 1019 tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainId)) 1020 if err != nil { 1021 t.Fatal(err) 1022 } 1023 block.AddTx(tx) 1024 } 1025 }) 1026 1027 if _, err := blockchain.InsertChain(blocks); err != nil { 1028 t.Fatal(err) 1029 } 1030 block := blockchain.GetBlockByNumber(1) 1031 if block.Transactions()[0].Protected() { 1032 t.Error("Expected block[0].txs[0] to not be replay protected") 1033 } 1034 1035 block = blockchain.GetBlockByNumber(3) 1036 if block.Transactions()[0].Protected() { 1037 t.Error("Expected block[3].txs[0] to not be replay protected") 1038 } 1039 if !block.Transactions()[1].Protected() { 1040 t.Error("Expected block[3].txs[1] to be replay protected") 1041 } 1042 if _, err := blockchain.InsertChain(blocks[4:]); err != nil { 1043 t.Fatal(err) 1044 } 1045 1046 config := ¶ms.ChainConfig{ChainId: big.NewInt(2), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)} 1047 blocks, _ = GenerateChain(config, blocks[len(blocks)-1], nil, db, 4, func(i int, block *BlockGen) { 1048 var ( 1049 tx *types.Transaction 1050 err error 1051 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1052 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 100000, new(big.Int), nil), signer, key) 1053 } 1054 ) 1055 switch i { 1056 case 0: 1057 tx, err = basicTx(types.NewEIP155Signer(big.NewInt(2))) 1058 if err != nil { 1059 t.Fatal(err) 1060 } 1061 block.AddTx(tx) 1062 } 1063 }) 1064 _, err := blockchain.InsertChain(blocks) 1065 if err != types.ErrInvalidChainId { 1066 t.Error("expected error:", types.ErrInvalidChainId) 1067 } 1068 } 1069 1070 func TestEIP161AccountRemoval(t *testing.T) { 1071 1072 var ( 1073 db = rawdb.NewMemoryDatabase() 1074 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1075 address = crypto.PubkeyToAddress(key.PublicKey) 1076 funds = big.NewInt(1000000000) 1077 theAddr = common.Address{1} 1078 gspec = &Genesis{ 1079 Config: ¶ms.ChainConfig{ 1080 ChainId: big.NewInt(1), 1081 HomesteadBlock: new(big.Int), 1082 EIP155Block: new(big.Int), 1083 EIP158Block: big.NewInt(2), 1084 }, 1085 Alloc: GenesisAlloc{address: {Balance: funds}}, 1086 } 1087 genesis = gspec.MustCommit(db) 1088 ) 1089 blockchain, _ := NewBlockChain(db, nil, gspec.Config, nil, vm.Config{}, nil) 1090 defer blockchain.Stop() 1091 1092 blocks, _ := GenerateChain(gspec.Config, genesis, nil, db, 3, func(i int, block *BlockGen) { 1093 var ( 1094 tx *types.Transaction 1095 err error 1096 signer = types.NewEIP155Signer(gspec.Config.ChainId) 1097 ) 1098 switch i { 1099 case 0: 1100 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 100000, new(big.Int), nil), signer, key) 1101 case 1: 1102 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 100000, new(big.Int), nil), signer, key) 1103 case 2: 1104 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 100000, new(big.Int), nil), signer, key) 1105 } 1106 if err != nil { 1107 t.Fatal(err) 1108 } 1109 block.AddTx(tx) 1110 }) 1111 1112 if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { 1113 t.Fatal(err) 1114 } 1115 if st, _ := blockchain.State(); !st.Exist(theAddr) { 1116 t.Error("expected account to exist") 1117 } 1118 1119 if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil { 1120 t.Fatal(err) 1121 } 1122 if st, _ := blockchain.State(); st.Exist(theAddr) { 1123 t.Error("account should not exist") 1124 } 1125 1126 if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil { 1127 t.Fatal(err) 1128 } 1129 if st, _ := blockchain.State(); st.Exist(theAddr) { 1130 t.Error("account should not exist") 1131 } 1132 } 1133 1134 func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { 1135 1136 engine := nil 1137 1138 db := rawdb.NewMemoryDatabase() 1139 genesis := new(Genesis).MustCommit(db) 1140 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1141 1142 forks := make([]*types.Block, len(blocks)) 1143 for i := 0; i < len(forks); i++ { 1144 parent := genesis 1145 if i > 0 { 1146 parent = blocks[i-1] 1147 } 1148 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1149 forks[i] = fork[0] 1150 } 1151 1152 diskdb := rawdb.NewMemoryDatabase() 1153 new(Genesis).MustCommit(diskdb) 1154 1155 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1156 if err != nil { 1157 t.Fatalf("failed to create tester chain: %v", err) 1158 } 1159 for i := 0; i < len(blocks); i++ { 1160 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1161 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1162 } 1163 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1164 t.Errorf("block %d: current block/header mismatch: block #%d [%x…], header #%d [%x…]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4]) 1165 } 1166 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1167 t.Fatalf(" fork %d: failed to insert into chain: %v", i, err) 1168 } 1169 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1170 t.Errorf(" fork %d: current block/header mismatch: block #%d [%x…], header #%d [%x…]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4]) 1171 } 1172 } 1173 } 1174 1175 func TestTrieForkGC(t *testing.T) { 1176 1177 engine := nil 1178 1179 db := rawdb.NewMemoryDatabase() 1180 genesis := new(Genesis).MustCommit(db) 1181 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1182 1183 forks := make([]*types.Block, len(blocks)) 1184 for i := 0; i < len(forks); i++ { 1185 parent := genesis 1186 if i > 0 { 1187 parent = blocks[i-1] 1188 } 1189 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1190 forks[i] = fork[0] 1191 } 1192 1193 diskdb := rawdb.NewMemoryDatabase() 1194 new(Genesis).MustCommit(diskdb) 1195 1196 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1197 if err != nil { 1198 t.Fatalf("failed to create tester chain: %v", err) 1199 } 1200 for i := 0; i < len(blocks); i++ { 1201 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1202 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1203 } 1204 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1205 t.Fatalf("fork %d: failed to insert into chain: %v", i, err) 1206 } 1207 } 1208 1209 for i := 0; i < triesInMemory; i++ { 1210 chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root()) 1211 chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root()) 1212 } 1213 if len(chain.stateCache.TrieDB().Nodes()) > 0 { 1214 t.Fatalf("stale tries still alive after garbase collection") 1215 } 1216 } 1217 1218 func TestLargeReorgTrieGC(t *testing.T) { 1219 1220 engine := nil 1221 1222 db := rawdb.NewMemoryDatabase() 1223 genesis := new(Genesis).MustCommit(db) 1224 1225 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1226 original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1227 competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) 1228 1229 diskdb := rawdb.NewMemoryDatabase() 1230 new(Genesis).MustCommit(diskdb) 1231 1232 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1233 if err != nil { 1234 t.Fatalf("failed to create tester chain: %v", err) 1235 } 1236 if _, err := chain.InsertChain(shared); err != nil { 1237 t.Fatalf("failed to insert shared chain: %v", err) 1238 } 1239 if _, err := chain.InsertChain(original); err != nil { 1240 t.Fatalf("failed to insert shared chain: %v", err) 1241 } 1242 1243 if node, _ := chain.stateCache.TrieDB().Node(shared[len(shared)-1].Root()); node != nil { 1244 t.Fatalf("common-but-old ancestor still cache") 1245 } 1246 1247 if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil { 1248 t.Fatalf("failed to insert competitor chain: %v", err) 1249 } 1250 for i, block := range competitor[:len(competitor)-2] { 1251 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1252 t.Fatalf("competitor %d: low TD chain became processed", i) 1253 } 1254 } 1255 1256 if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil { 1257 t.Fatalf("failed to finalize competitor chain: %v", err) 1258 } 1259 for i, block := range competitor[:len(competitor)-triesInMemory] { 1260 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1261 t.Fatalf("competitor %d: competing chain state missing", i) 1262 } 1263 } 1264 }