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