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