github.com/codingfuture/orig-energi3@v0.8.4/core/blockchain_test.go (about) 1 // Copyright 2018 The Energi Core Authors 2 // Copyright 2014 The go-ethereum Authors 3 // This file is part of the Energi Core library. 4 // 5 // The Energi Core library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The Energi Core library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the Energi Core library. If not, see <http://www.gnu.org/licenses/>. 17 18 package core 19 20 import ( 21 "fmt" 22 "math/big" 23 "math/rand" 24 "sync" 25 "testing" 26 "time" 27 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/consensus" 30 "github.com/ethereum/go-ethereum/consensus/ethash" 31 "github.com/ethereum/go-ethereum/core/rawdb" 32 "github.com/ethereum/go-ethereum/core/state" 33 "github.com/ethereum/go-ethereum/core/types" 34 "github.com/ethereum/go-ethereum/core/vm" 35 "github.com/ethereum/go-ethereum/crypto" 36 "github.com/ethereum/go-ethereum/ethdb" 37 "github.com/ethereum/go-ethereum/params" 38 ) 39 40 // So we can deterministically seed different blockchains 41 var ( 42 canonicalSeed = 1 43 forkSeed = 2 44 ) 45 46 // newCanonical creates a chain database, and injects a deterministic canonical 47 // chain. Depending on the full flag, if creates either a full block chain or a 48 // header only chain. 49 func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *BlockChain, error) { 50 var ( 51 db = ethdb.NewMemDatabase() 52 genesis = new(Genesis).MustCommit(db) 53 ) 54 55 // Initialize a fresh chain with only a genesis block 56 blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil) 57 // Create and inject the requested chain 58 if n == 0 { 59 return db, blockchain, nil 60 } 61 if full { 62 // Full block-chain requested 63 blocks := makeBlockChain(genesis, n, engine, db, canonicalSeed) 64 _, err := blockchain.InsertChain(blocks) 65 return db, blockchain, err 66 } 67 // Header-only chain requested 68 headers := makeHeaderChain(genesis.Header(), n, engine, db, canonicalSeed) 69 _, err := blockchain.InsertHeaderChain(headers, 1) 70 return db, blockchain, err 71 } 72 73 // Test fork of length N starting from block i 74 func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) { 75 // Copy old chain up to #i into a new db 76 db, blockchain2, err := newCanonical(ethash.NewFaker(), i, full) 77 if err != nil { 78 t.Fatal("could not make new canonical in testFork", err) 79 } 80 defer blockchain2.Stop() 81 82 // Assert the chains have the same header/block at #i 83 var hash1, hash2 common.Hash 84 if full { 85 hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash() 86 hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash() 87 } else { 88 hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash() 89 hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash() 90 } 91 if hash1 != hash2 { 92 t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) 93 } 94 // Extend the newly created chain 95 var ( 96 blockChainB []*types.Block 97 headerChainB []*types.Header 98 ) 99 if full { 100 blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed) 101 if _, err := blockchain2.InsertChain(blockChainB); err != nil { 102 t.Fatalf("failed to insert forking chain: %v", err) 103 } 104 } else { 105 headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, ethash.NewFaker(), db, forkSeed) 106 if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil { 107 t.Fatalf("failed to insert forking chain: %v", err) 108 } 109 } 110 // Sanity check that the forked chain can be imported into the original 111 var tdPre, tdPost *big.Int 112 113 if full { 114 tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()) 115 if err := testBlockChainImport(blockChainB, blockchain); err != nil { 116 t.Fatalf("failed to import forked block chain: %v", err) 117 } 118 tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash()) 119 } else { 120 tdPre = blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()) 121 if err := testHeaderChainImport(headerChainB, blockchain); err != nil { 122 t.Fatalf("failed to import forked header chain: %v", err) 123 } 124 tdPost = blockchain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash()) 125 } 126 // Compare the total difficulties of the chains 127 comparator(tdPre, tdPost) 128 } 129 130 func printChain(bc *BlockChain) { 131 for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- { 132 b := bc.GetBlockByNumber(uint64(i)) 133 fmt.Printf("\t%x %v\n", b.Hash(), b.Difficulty()) 134 } 135 } 136 137 // testBlockChainImport tries to process a chain of blocks, writing them into 138 // the database if successful. 139 func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { 140 for _, block := range chain { 141 // Try and process the block 142 err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) 143 if err == nil { 144 err = blockchain.validator.ValidateBody(block) 145 } 146 if err != nil { 147 if err == ErrKnownBlock { 148 continue 149 } 150 return err 151 } 152 statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache) 153 if err != nil { 154 return err 155 } 156 receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, vm.Config{}) 157 if err != nil { 158 blockchain.reportBlock(block, receipts, err) 159 return err 160 } 161 err = blockchain.validator.ValidateState(block, blockchain.GetBlockByHash(block.ParentHash()), statedb, receipts, usedGas) 162 if err != nil { 163 blockchain.reportBlock(block, receipts, err) 164 return err 165 } 166 blockchain.mu.Lock() 167 rawdb.WriteTd(blockchain.db, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash()))) 168 rawdb.WriteBlock(blockchain.db, block) 169 statedb.Commit(false) 170 blockchain.mu.Unlock() 171 } 172 return nil 173 } 174 175 // testHeaderChainImport tries to process a chain of header, writing them into 176 // the database if successful. 177 func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { 178 for _, header := range chain { 179 // Try and validate the header 180 if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil { 181 return err 182 } 183 // Manually insert the header into the database, but don't reorganise (allows subsequent testing) 184 blockchain.mu.Lock() 185 rawdb.WriteTd(blockchain.db, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash))) 186 rawdb.WriteHeader(blockchain.db, header) 187 blockchain.mu.Unlock() 188 } 189 return nil 190 } 191 192 func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *testing.T) { 193 _, err := blockchain.InsertChain(chain) 194 if err != nil { 195 fmt.Println(err) 196 t.FailNow() 197 } 198 done <- true 199 } 200 201 func TestLastBlock(t *testing.T) { 202 _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) 203 if err != nil { 204 t.Fatalf("failed to create pristine chain: %v", err) 205 } 206 defer blockchain.Stop() 207 208 blocks := makeBlockChain(blockchain.CurrentBlock(), 1, ethash.NewFullFaker(), blockchain.db, 0) 209 if _, err := blockchain.InsertChain(blocks); err != nil { 210 t.Fatalf("Failed to insert block: %v", err) 211 } 212 if blocks[len(blocks)-1].Hash() != rawdb.ReadHeadBlockHash(blockchain.db) { 213 t.Fatalf("Write/Get HeadBlockHash failed") 214 } 215 } 216 217 // Tests that given a starting canonical chain of a given size, it can be extended 218 // with various length chains. 219 func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) } 220 func TestExtendCanonicalBlocks(t *testing.T) { testExtendCanonical(t, true) } 221 222 func testExtendCanonical(t *testing.T, full bool) { 223 length := 5 224 225 // Make first chain starting from genesis 226 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 227 if err != nil { 228 t.Fatalf("failed to make new canonical chain: %v", err) 229 } 230 defer processor.Stop() 231 232 // Define the difficulty comparator 233 better := func(td1, td2 *big.Int) { 234 if td2.Cmp(td1) <= 0 { 235 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 236 } 237 } 238 // Start fork from current height 239 testFork(t, processor, length, 1, full, better) 240 testFork(t, processor, length, 2, full, better) 241 testFork(t, processor, length, 5, full, better) 242 testFork(t, processor, length, 10, full, better) 243 } 244 245 // Tests that given a starting canonical chain of a given size, creating shorter 246 // forks do not take canonical ownership. 247 func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) } 248 func TestShorterForkBlocks(t *testing.T) { testShorterFork(t, true) } 249 250 func testShorterFork(t *testing.T, full bool) { 251 length := 10 252 253 // Make first chain starting from genesis 254 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 255 if err != nil { 256 t.Fatalf("failed to make new canonical chain: %v", err) 257 } 258 defer processor.Stop() 259 260 // Define the difficulty comparator 261 worse := func(td1, td2 *big.Int) { 262 if td2.Cmp(td1) >= 0 { 263 t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) 264 } 265 } 266 // Sum of numbers must be less than `length` for this to be a shorter fork 267 testFork(t, processor, 0, 3, full, worse) 268 testFork(t, processor, 0, 7, full, worse) 269 testFork(t, processor, 1, 1, full, worse) 270 testFork(t, processor, 1, 7, full, worse) 271 testFork(t, processor, 5, 3, full, worse) 272 testFork(t, processor, 5, 4, full, worse) 273 } 274 275 // Tests that given a starting canonical chain of a given size, creating longer 276 // forks do take canonical ownership. 277 func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) } 278 func TestLongerForkBlocks(t *testing.T) { testLongerFork(t, true) } 279 280 func testLongerFork(t *testing.T, full bool) { 281 length := 10 282 283 // Make first chain starting from genesis 284 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 285 if err != nil { 286 t.Fatalf("failed to make new canonical chain: %v", err) 287 } 288 defer processor.Stop() 289 290 // Define the difficulty comparator 291 better := func(td1, td2 *big.Int) { 292 if td2.Cmp(td1) <= 0 { 293 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 294 } 295 } 296 // Sum of numbers must be greater than `length` for this to be a longer fork 297 testFork(t, processor, 0, 11, full, better) 298 testFork(t, processor, 0, 15, full, better) 299 testFork(t, processor, 1, 10, full, better) 300 testFork(t, processor, 1, 12, full, better) 301 testFork(t, processor, 5, 6, full, better) 302 testFork(t, processor, 5, 8, full, better) 303 } 304 305 // Tests that given a starting canonical chain of a given size, creating equal 306 // forks do take canonical ownership. 307 func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) } 308 func TestEqualForkBlocks(t *testing.T) { testEqualFork(t, true) } 309 310 func testEqualFork(t *testing.T, full bool) { 311 length := 10 312 313 // Make first chain starting from genesis 314 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 315 if err != nil { 316 t.Fatalf("failed to make new canonical chain: %v", err) 317 } 318 defer processor.Stop() 319 320 // Define the difficulty comparator 321 equal := func(td1, td2 *big.Int) { 322 if td2.Cmp(td1) != 0 { 323 t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) 324 } 325 } 326 // Sum of numbers must be equal to `length` for this to be an equal fork 327 testFork(t, processor, 0, 10, full, equal) 328 testFork(t, processor, 1, 9, full, equal) 329 testFork(t, processor, 2, 8, full, equal) 330 testFork(t, processor, 5, 5, full, equal) 331 testFork(t, processor, 6, 4, full, equal) 332 testFork(t, processor, 9, 1, full, equal) 333 } 334 335 // Tests that chains missing links do not get accepted by the processor. 336 func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) } 337 func TestBrokenBlockChain(t *testing.T) { testBrokenChain(t, true) } 338 339 func testBrokenChain(t *testing.T, full bool) { 340 // Make chain starting from genesis 341 db, blockchain, err := newCanonical(ethash.NewFaker(), 10, full) 342 if err != nil { 343 t.Fatalf("failed to make new canonical chain: %v", err) 344 } 345 defer blockchain.Stop() 346 347 // Create a forked chain, and try to insert with a missing link 348 if full { 349 chain := makeBlockChain(blockchain.CurrentBlock(), 5, ethash.NewFaker(), db, forkSeed)[1:] 350 if err := testBlockChainImport(chain, blockchain); err == nil { 351 t.Errorf("broken block chain not reported") 352 } 353 } else { 354 chain := makeHeaderChain(blockchain.CurrentHeader(), 5, ethash.NewFaker(), db, forkSeed)[1:] 355 if err := testHeaderChainImport(chain, blockchain); err == nil { 356 t.Errorf("broken header chain not reported") 357 } 358 } 359 } 360 361 // Tests that reorganising a long difficult chain after a short easy one 362 // overwrites the canonical numbers and links in the database. 363 func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) } 364 func TestReorgLongBlocks(t *testing.T) { testReorgLong(t, true) } 365 366 func testReorgLong(t *testing.T, full bool) { 367 testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280, full) 368 } 369 370 // Tests that reorganising a short difficult chain after a long easy one 371 // overwrites the canonical numbers and links in the database. 372 func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false) } 373 func TestReorgShortBlocks(t *testing.T) { testReorgShort(t, true) } 374 375 func testReorgShort(t *testing.T, full bool) { 376 // Create a long easy chain vs. a short heavy one. Due to difficulty adjustment 377 // we need a fairly long chain of blocks with different difficulties for a short 378 // one to become heavyer than a long one. The 96 is an empirical value. 379 easy := make([]int64, 96) 380 for i := 0; i < len(easy); i++ { 381 easy[i] = 60 382 } 383 diff := make([]int64, len(easy)-1) 384 for i := 0; i < len(diff); i++ { 385 diff[i] = -9 386 } 387 testReorg(t, easy, diff, 12615120, full) 388 } 389 390 func testReorg(t *testing.T, first, second []int64, td int64, full bool) { 391 // Create a pristine chain and database 392 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 393 if err != nil { 394 t.Fatalf("failed to create pristine chain: %v", err) 395 } 396 defer blockchain.Stop() 397 398 // Insert an easy and a difficult chain afterwards 399 easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db, len(first), func(i int, b *BlockGen) { 400 b.OffsetTime(first[i]) 401 }) 402 diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db, len(second), func(i int, b *BlockGen) { 403 b.OffsetTime(second[i]) 404 }) 405 if full { 406 if _, err := blockchain.InsertChain(easyBlocks); err != nil { 407 t.Fatalf("failed to insert easy chain: %v", err) 408 } 409 if _, err := blockchain.InsertChain(diffBlocks); err != nil { 410 t.Fatalf("failed to insert difficult chain: %v", err) 411 } 412 } else { 413 easyHeaders := make([]*types.Header, len(easyBlocks)) 414 for i, block := range easyBlocks { 415 easyHeaders[i] = block.Header() 416 } 417 diffHeaders := make([]*types.Header, len(diffBlocks)) 418 for i, block := range diffBlocks { 419 diffHeaders[i] = block.Header() 420 } 421 if _, err := blockchain.InsertHeaderChain(easyHeaders, 1); err != nil { 422 t.Fatalf("failed to insert easy chain: %v", err) 423 } 424 if _, err := blockchain.InsertHeaderChain(diffHeaders, 1); err != nil { 425 t.Fatalf("failed to insert difficult chain: %v", err) 426 } 427 } 428 // Check that the chain is valid number and link wise 429 if full { 430 prev := blockchain.CurrentBlock() 431 for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, blockchain.GetBlockByNumber(block.NumberU64()-1) { 432 if prev.ParentHash() != block.Hash() { 433 t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash(), block.Hash()) 434 } 435 } 436 } else { 437 prev := blockchain.CurrentHeader() 438 for header := blockchain.GetHeaderByNumber(blockchain.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, blockchain.GetHeaderByNumber(header.Number.Uint64()-1) { 439 if prev.ParentHash != header.Hash() { 440 t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash()) 441 } 442 } 443 } 444 // Make sure the chain total difficulty is the correct one 445 want := new(big.Int).Add(blockchain.genesisBlock.Difficulty(), big.NewInt(td)) 446 if full { 447 if have := blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()); have.Cmp(want) != 0 { 448 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 449 } 450 } else { 451 if have := blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()); have.Cmp(want) != 0 { 452 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 453 } 454 } 455 } 456 457 // Tests that the insertion functions detect banned hashes. 458 func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) } 459 func TestBadBlockHashes(t *testing.T) { testBadHashes(t, true) } 460 461 func testBadHashes(t *testing.T, full bool) { 462 // Create a pristine chain and database 463 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 464 if err != nil { 465 t.Fatalf("failed to create pristine chain: %v", err) 466 } 467 defer blockchain.Stop() 468 469 // Create a chain, ban a hash and try to import 470 if full { 471 blocks := makeBlockChain(blockchain.CurrentBlock(), 3, ethash.NewFaker(), db, 10) 472 473 BadHashes[blocks[2].Header().Hash()] = true 474 defer func() { delete(BadHashes, blocks[2].Header().Hash()) }() 475 476 _, err = blockchain.InsertChain(blocks) 477 } else { 478 headers := makeHeaderChain(blockchain.CurrentHeader(), 3, ethash.NewFaker(), db, 10) 479 480 BadHashes[headers[2].Hash()] = true 481 defer func() { delete(BadHashes, headers[2].Hash()) }() 482 483 _, err = blockchain.InsertHeaderChain(headers, 1) 484 } 485 if err != ErrBlacklistedHash { 486 t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash) 487 } 488 } 489 490 // Tests that bad hashes are detected on boot, and the chain rolled back to a 491 // good state prior to the bad hash. 492 func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) } 493 func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) } 494 495 func testReorgBadHashes(t *testing.T, full bool) { 496 // Create a pristine chain and database 497 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 498 if err != nil { 499 t.Fatalf("failed to create pristine chain: %v", err) 500 } 501 // Create a chain, import and ban afterwards 502 headers := makeHeaderChain(blockchain.CurrentHeader(), 4, ethash.NewFaker(), db, 10) 503 blocks := makeBlockChain(blockchain.CurrentBlock(), 4, ethash.NewFaker(), db, 10) 504 505 if full { 506 if _, err = blockchain.InsertChain(blocks); err != nil { 507 t.Errorf("failed to import blocks: %v", err) 508 } 509 if blockchain.CurrentBlock().Hash() != blocks[3].Hash() { 510 t.Errorf("last block hash mismatch: have: %x, want %x", blockchain.CurrentBlock().Hash(), blocks[3].Header().Hash()) 511 } 512 BadHashes[blocks[3].Header().Hash()] = true 513 defer func() { delete(BadHashes, blocks[3].Header().Hash()) }() 514 } else { 515 if _, err = blockchain.InsertHeaderChain(headers, 1); err != nil { 516 t.Errorf("failed to import headers: %v", err) 517 } 518 if blockchain.CurrentHeader().Hash() != headers[3].Hash() { 519 t.Errorf("last header hash mismatch: have: %x, want %x", blockchain.CurrentHeader().Hash(), headers[3].Hash()) 520 } 521 BadHashes[headers[3].Hash()] = true 522 defer func() { delete(BadHashes, headers[3].Hash()) }() 523 } 524 blockchain.Stop() 525 526 // Create a new BlockChain and check that it rolled back the state. 527 ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, ethash.NewFaker(), vm.Config{}, nil) 528 if err != nil { 529 t.Fatalf("failed to create new chain manager: %v", err) 530 } 531 if full { 532 if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() { 533 t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash()) 534 } 535 if blocks[2].Header().GasLimit != ncm.GasLimit() { 536 t.Errorf("last block gasLimit mismatch: have: %d, want %d", ncm.GasLimit(), blocks[2].Header().GasLimit) 537 } 538 } else { 539 if ncm.CurrentHeader().Hash() != headers[2].Hash() { 540 t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) 541 } 542 } 543 ncm.Stop() 544 } 545 546 // Tests chain insertions in the face of one entity containing an invalid nonce. 547 func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) } 548 func TestBlocksInsertNonceError(t *testing.T) { testInsertNonceError(t, true) } 549 550 func testInsertNonceError(t *testing.T, full bool) { 551 for i := 1; i < 25 && !t.Failed(); i++ { 552 // Create a pristine chain and database 553 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 554 if err != nil { 555 t.Fatalf("failed to create pristine chain: %v", err) 556 } 557 defer blockchain.Stop() 558 559 // Create and insert a chain with a failing nonce 560 var ( 561 failAt int 562 failRes int 563 failNum uint64 564 ) 565 if full { 566 blocks := makeBlockChain(blockchain.CurrentBlock(), i, ethash.NewFaker(), db, 0) 567 568 failAt = rand.Int() % len(blocks) 569 failNum = blocks[failAt].NumberU64() 570 571 blockchain.engine = ethash.NewFakeFailer(failNum) 572 failRes, err = blockchain.InsertChain(blocks) 573 } else { 574 headers := makeHeaderChain(blockchain.CurrentHeader(), i, ethash.NewFaker(), db, 0) 575 576 failAt = rand.Int() % len(headers) 577 failNum = headers[failAt].Number.Uint64() 578 579 blockchain.engine = ethash.NewFakeFailer(failNum) 580 blockchain.hc.engine = blockchain.engine 581 failRes, err = blockchain.InsertHeaderChain(headers, 1) 582 } 583 // Check that the returned error indicates the failure 584 if failRes != failAt { 585 t.Errorf("test %d: failure (%v) index mismatch: have %d, want %d", i, err, failRes, failAt) 586 } 587 // Check that all blocks after the failing block have been inserted 588 for j := 0; j < i-failAt; j++ { 589 if full { 590 if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil { 591 t.Errorf("test %d: invalid block in chain: %v", i, block) 592 } 593 } else { 594 if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil { 595 t.Errorf("test %d: invalid header in chain: %v", i, header) 596 } 597 } 598 } 599 } 600 } 601 602 // Tests that fast importing a block chain produces the same chain data as the 603 // classical full block processing. 604 func TestFastVsFullChains(t *testing.T) { 605 // Configure and generate a sample block chain 606 var ( 607 gendb = ethdb.NewMemDatabase() 608 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 609 address = crypto.PubkeyToAddress(key.PublicKey) 610 funds = big.NewInt(1000000000) 611 gspec = &Genesis{ 612 Config: params.TestChainConfig, 613 Alloc: GenesisAlloc{address: {Balance: funds}}, 614 } 615 genesis = gspec.MustCommit(gendb) 616 signer = types.NewEIP155Signer(gspec.Config.ChainID) 617 ) 618 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, 1024, func(i int, block *BlockGen) { 619 block.SetCoinbase(common.Address{0x00}) 620 621 // If the block number is multiple of 3, send a few bonus transactions to the miner 622 if i%3 == 2 { 623 for j := 0; j < i%4+1; j++ { 624 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key) 625 if err != nil { 626 panic(err) 627 } 628 block.AddTx(tx) 629 } 630 } 631 // If the block number is a multiple of 5, add a few bonus uncles to the block 632 if i%5 == 5 { 633 block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))}) 634 } 635 }) 636 // Import the chain as an archive node for the comparison baseline 637 archiveDb := ethdb.NewMemDatabase() 638 gspec.MustCommit(archiveDb) 639 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 640 defer archive.Stop() 641 642 if n, err := archive.InsertChain(blocks); err != nil { 643 t.Fatalf("failed to process block %d: %v", n, err) 644 } 645 // Fast import the chain as a non-archive node to test 646 fastDb := ethdb.NewMemDatabase() 647 gspec.MustCommit(fastDb) 648 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 649 defer fast.Stop() 650 651 headers := make([]*types.Header, len(blocks)) 652 for i, block := range blocks { 653 headers[i] = block.Header() 654 } 655 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 656 t.Fatalf("failed to insert header %d: %v", n, err) 657 } 658 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 659 t.Fatalf("failed to insert receipt %d: %v", n, err) 660 } 661 // Iterate over all chain data components, and cross reference 662 for i := 0; i < len(blocks); i++ { 663 num, hash := blocks[i].NumberU64(), blocks[i].Hash() 664 665 if ftd, atd := fast.GetTdByHash(hash), archive.GetTdByHash(hash); ftd.Cmp(atd) != 0 { 666 t.Errorf("block #%d [%x]: td mismatch: have %v, want %v", num, hash, ftd, atd) 667 } 668 if fheader, aheader := fast.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); fheader.Hash() != aheader.Hash() { 669 t.Errorf("block #%d [%x]: header mismatch: have %v, want %v", num, hash, fheader, aheader) 670 } 671 if fblock, ablock := fast.GetBlockByHash(hash), archive.GetBlockByHash(hash); fblock.Hash() != ablock.Hash() { 672 t.Errorf("block #%d [%x]: block mismatch: have %v, want %v", num, hash, fblock, ablock) 673 } else if types.DeriveSha(fblock.Transactions()) != types.DeriveSha(ablock.Transactions()) { 674 t.Errorf("block #%d [%x]: transactions mismatch: have %v, want %v", num, hash, fblock.Transactions(), ablock.Transactions()) 675 } else if types.CalcUncleHash(fblock.Uncles()) != types.CalcUncleHash(ablock.Uncles()) { 676 t.Errorf("block #%d [%x]: uncles mismatch: have %v, want %v", num, hash, fblock.Uncles(), ablock.Uncles()) 677 } 678 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) { 679 t.Errorf("block #%d [%x]: receipts mismatch: have %v, want %v", num, hash, freceipts, areceipts) 680 } 681 } 682 // Check that the canonical chains are the same between the databases 683 for i := 0; i < len(blocks)+1; i++ { 684 if fhash, ahash := rawdb.ReadCanonicalHash(fastDb, uint64(i)), rawdb.ReadCanonicalHash(archiveDb, uint64(i)); fhash != ahash { 685 t.Errorf("block #%d: canonical hash mismatch: have %v, want %v", i, fhash, ahash) 686 } 687 } 688 } 689 690 // Tests that various import methods move the chain head pointers to the correct 691 // positions. 692 func TestLightVsFastVsFullChainHeads(t *testing.T) { 693 // Configure and generate a sample block chain 694 var ( 695 gendb = ethdb.NewMemDatabase() 696 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 697 address = crypto.PubkeyToAddress(key.PublicKey) 698 funds = big.NewInt(1000000000) 699 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 700 genesis = gspec.MustCommit(gendb) 701 ) 702 height := uint64(1024) 703 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil) 704 705 // Configure a subchain to roll back 706 remove := []common.Hash{} 707 for _, block := range blocks[height/2:] { 708 remove = append(remove, block.Hash()) 709 } 710 // Create a small assertion method to check the three heads 711 assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { 712 if num := chain.CurrentBlock().NumberU64(); num != block { 713 t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) 714 } 715 if num := chain.CurrentFastBlock().NumberU64(); num != fast { 716 t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast) 717 } 718 if num := chain.CurrentHeader().Number.Uint64(); num != header { 719 t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header) 720 } 721 } 722 // Import the chain as an archive node and ensure all pointers are updated 723 archiveDb := ethdb.NewMemDatabase() 724 gspec.MustCommit(archiveDb) 725 726 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 727 if n, err := archive.InsertChain(blocks); err != nil { 728 t.Fatalf("failed to process block %d: %v", n, err) 729 } 730 defer archive.Stop() 731 732 assert(t, "archive", archive, height, height, height) 733 archive.Rollback(remove) 734 assert(t, "archive", archive, height/2, height/2, height/2) 735 736 // Import the chain as a non-archive node and ensure all pointers are updated 737 fastDb := ethdb.NewMemDatabase() 738 gspec.MustCommit(fastDb) 739 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 740 defer fast.Stop() 741 742 headers := make([]*types.Header, len(blocks)) 743 for i, block := range blocks { 744 headers[i] = block.Header() 745 } 746 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 747 t.Fatalf("failed to insert header %d: %v", n, err) 748 } 749 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 750 t.Fatalf("failed to insert receipt %d: %v", n, err) 751 } 752 assert(t, "fast", fast, height, height, 0) 753 fast.Rollback(remove) 754 assert(t, "fast", fast, height/2, height/2, 0) 755 756 // Import the chain as a light node and ensure all pointers are updated 757 lightDb := ethdb.NewMemDatabase() 758 gspec.MustCommit(lightDb) 759 760 light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 761 if n, err := light.InsertHeaderChain(headers, 1); err != nil { 762 t.Fatalf("failed to insert header %d: %v", n, err) 763 } 764 defer light.Stop() 765 766 assert(t, "light", light, height, 0, 0) 767 light.Rollback(remove) 768 assert(t, "light", light, height/2, 0, 0) 769 } 770 771 // Tests that chain reorganisations handle transaction removals and reinsertions. 772 func TestChainTxReorgs(t *testing.T) { 773 var ( 774 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 775 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 776 key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 777 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 778 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 779 addr3 = crypto.PubkeyToAddress(key3.PublicKey) 780 db = ethdb.NewMemDatabase() 781 gspec = &Genesis{ 782 Config: params.TestChainConfig, 783 GasLimit: 40000000, 784 Alloc: GenesisAlloc{ 785 addr1: {Balance: big.NewInt(10000000)}, 786 addr2: {Balance: big.NewInt(10000000)}, 787 addr3: {Balance: big.NewInt(10000000)}, 788 }, 789 } 790 genesis = gspec.MustCommit(db) 791 signer = types.NewEIP155Signer(gspec.Config.ChainID) 792 ) 793 794 // Create two transactions shared between the chains: 795 // - postponed: transaction included at a later block in the forked chain 796 // - swapped: transaction included at the same block number in the forked chain 797 postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 798 swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 799 800 // Create two transactions that will be dropped by the forked chain: 801 // - pastDrop: transaction dropped retroactively from a past block 802 // - freshDrop: transaction dropped exactly at the block where the reorg is detected 803 var pastDrop, freshDrop *types.Transaction 804 805 // Create three transactions that will be added in the forked chain: 806 // - pastAdd: transaction added before the reorganization is detected 807 // - freshAdd: transaction added at the exact block the reorg is detected 808 // - futureAdd: transaction added after the reorg has already finished 809 var pastAdd, freshAdd, futureAdd *types.Transaction 810 811 chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) { 812 switch i { 813 case 0: 814 pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 815 816 gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point 817 gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork 818 819 case 2: 820 freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 821 822 gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point 823 gen.AddTx(swapped) // This transaction will be swapped out at the exact height 824 825 gen.OffsetTime(9) // Lower the block difficulty to simulate a weaker chain 826 } 827 }) 828 // Import the chain. This runs all block validation rules. 829 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 830 if i, err := blockchain.InsertChain(chain); err != nil { 831 t.Fatalf("failed to insert original chain[%d]: %v", i, err) 832 } 833 defer blockchain.Stop() 834 835 // overwrite the old chain 836 chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) { 837 switch i { 838 case 0: 839 pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 840 gen.AddTx(pastAdd) // This transaction needs to be injected during reorg 841 842 case 2: 843 gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain 844 gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain 845 846 freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 847 gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time 848 849 case 3: 850 futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 851 gen.AddTx(futureAdd) // This transaction will be added after a full reorg 852 } 853 }) 854 if _, err := blockchain.InsertChain(chain); err != nil { 855 t.Fatalf("failed to insert forked chain: %v", err) 856 } 857 858 // removed tx 859 for i, tx := range (types.Transactions{pastDrop, freshDrop}) { 860 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn != nil { 861 t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) 862 } 863 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt != nil { 864 t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt) 865 } 866 } 867 // added tx 868 for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) { 869 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 870 t.Errorf("add %d: expected tx to be found", i) 871 } 872 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt == nil { 873 t.Errorf("add %d: expected receipt to be found", i) 874 } 875 } 876 // shared tx 877 for i, tx := range (types.Transactions{postponed, swapped}) { 878 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 879 t.Errorf("share %d: expected tx to be found", i) 880 } 881 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash()); rcpt == nil { 882 t.Errorf("share %d: expected receipt to be found", i) 883 } 884 } 885 } 886 887 func TestLogReorgs(t *testing.T) { 888 var ( 889 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 890 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 891 db = ethdb.NewMemDatabase() 892 // this code generates a log 893 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 894 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 895 genesis = gspec.MustCommit(db) 896 signer = types.NewEIP155Signer(gspec.Config.ChainID) 897 ) 898 899 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 900 defer blockchain.Stop() 901 902 rmLogsCh := make(chan RemovedLogsEvent) 903 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 904 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 905 if i == 1 { 906 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 907 if err != nil { 908 t.Fatalf("failed to create tx: %v", err) 909 } 910 gen.AddTx(tx) 911 } 912 }) 913 if _, err := blockchain.InsertChain(chain); err != nil { 914 t.Fatalf("failed to insert chain: %v", err) 915 } 916 917 chain, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 918 if _, err := blockchain.InsertChain(chain); err != nil { 919 t.Fatalf("failed to insert forked chain: %v", err) 920 } 921 922 timeout := time.NewTimer(1 * time.Second) 923 select { 924 case ev := <-rmLogsCh: 925 if len(ev.Logs) == 0 { 926 t.Error("expected logs") 927 } 928 case <-timeout.C: 929 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 930 } 931 } 932 933 func TestLogRebirth(t *testing.T) { 934 var ( 935 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 936 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 937 db = ethdb.NewMemDatabase() 938 939 // this code generates a log 940 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 941 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 942 genesis = gspec.MustCommit(db) 943 signer = types.NewEIP155Signer(gspec.Config.ChainID) 944 newLogCh = make(chan bool) 945 ) 946 947 // listenNewLog checks whether the received logs number is equal with expected. 948 listenNewLog := func(sink chan []*types.Log, expect int) { 949 cnt := 0 950 for { 951 select { 952 case logs := <-sink: 953 cnt += len(logs) 954 case <-time.NewTimer(5 * time.Second).C: 955 // new logs timeout 956 newLogCh <- false 957 return 958 } 959 if cnt == expect { 960 break 961 } else if cnt > expect { 962 // redundant logs received 963 newLogCh <- false 964 return 965 } 966 } 967 select { 968 case <-sink: 969 // redundant logs received 970 newLogCh <- false 971 case <-time.NewTimer(100 * time.Millisecond).C: 972 newLogCh <- true 973 } 974 } 975 976 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 977 defer blockchain.Stop() 978 979 logsCh := make(chan []*types.Log) 980 blockchain.SubscribeLogsEvent(logsCh) 981 982 rmLogsCh := make(chan RemovedLogsEvent) 983 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 984 985 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 986 if i == 1 { 987 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 988 if err != nil { 989 t.Fatalf("failed to create tx: %v", err) 990 } 991 gen.AddTx(tx) 992 } 993 }) 994 995 // Spawn a goroutine to receive log events 996 go listenNewLog(logsCh, 1) 997 if _, err := blockchain.InsertChain(chain); err != nil { 998 t.Fatalf("failed to insert chain: %v", err) 999 } 1000 if !<-newLogCh { 1001 t.Fatalf("failed to receive new log event") 1002 } 1003 1004 // Generate long reorg chain 1005 forkChain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1006 if i == 1 { 1007 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 1008 if err != nil { 1009 t.Fatalf("failed to create tx: %v", err) 1010 } 1011 gen.AddTx(tx) 1012 // Higher block difficulty 1013 gen.OffsetTime(-9) 1014 } 1015 }) 1016 1017 // Spawn a goroutine to receive log events 1018 go listenNewLog(logsCh, 1) 1019 if _, err := blockchain.InsertChain(forkChain); err != nil { 1020 t.Fatalf("failed to insert forked chain: %v", err) 1021 } 1022 if !<-newLogCh { 1023 t.Fatalf("failed to receive new log event") 1024 } 1025 // Ensure removedLog events received 1026 select { 1027 case ev := <-rmLogsCh: 1028 if len(ev.Logs) == 0 { 1029 t.Error("expected logs") 1030 } 1031 case <-time.NewTimer(1 * time.Second).C: 1032 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 1033 } 1034 1035 newBlocks, _ := GenerateChain(params.TestChainConfig, chain[len(chain)-1], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) 1036 go listenNewLog(logsCh, 1) 1037 if _, err := blockchain.InsertChain(newBlocks); err != nil { 1038 t.Fatalf("failed to insert forked chain: %v", err) 1039 } 1040 // Ensure removedLog events received 1041 select { 1042 case ev := <-rmLogsCh: 1043 if len(ev.Logs) == 0 { 1044 t.Error("expected logs") 1045 } 1046 case <-time.NewTimer(1 * time.Second).C: 1047 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 1048 } 1049 // Rebirth logs should omit a newLogEvent 1050 if !<-newLogCh { 1051 t.Fatalf("failed to receive new log event") 1052 } 1053 } 1054 1055 func TestSideLogRebirth(t *testing.T) { 1056 var ( 1057 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1058 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1059 db = ethdb.NewMemDatabase() 1060 1061 // this code generates a log 1062 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 1063 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 1064 genesis = gspec.MustCommit(db) 1065 signer = types.NewEIP155Signer(gspec.Config.ChainID) 1066 newLogCh = make(chan bool) 1067 ) 1068 1069 // listenNewLog checks whether the received logs number is equal with expected. 1070 listenNewLog := func(sink chan []*types.Log, expect int) { 1071 cnt := 0 1072 for { 1073 select { 1074 case logs := <-sink: 1075 cnt += len(logs) 1076 case <-time.NewTimer(5 * time.Second).C: 1077 // new logs timeout 1078 newLogCh <- false 1079 return 1080 } 1081 if cnt == expect { 1082 break 1083 } else if cnt > expect { 1084 // redundant logs received 1085 newLogCh <- false 1086 return 1087 } 1088 } 1089 select { 1090 case <-sink: 1091 // redundant logs received 1092 newLogCh <- false 1093 case <-time.NewTimer(100 * time.Millisecond).C: 1094 newLogCh <- true 1095 } 1096 } 1097 1098 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1099 defer blockchain.Stop() 1100 1101 logsCh := make(chan []*types.Log) 1102 blockchain.SubscribeLogsEvent(logsCh) 1103 1104 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1105 if i == 1 { 1106 // Higher block difficulty 1107 gen.OffsetTime(-9) 1108 } 1109 }) 1110 if _, err := blockchain.InsertChain(chain); err != nil { 1111 t.Fatalf("failed to insert forked chain: %v", err) 1112 } 1113 1114 // Generate side chain with lower difficulty 1115 sideChain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1116 if i == 1 { 1117 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 1118 if err != nil { 1119 t.Fatalf("failed to create tx: %v", err) 1120 } 1121 gen.AddTx(tx) 1122 } 1123 }) 1124 if _, err := blockchain.InsertChain(sideChain); err != nil { 1125 t.Fatalf("failed to insert forked chain: %v", err) 1126 } 1127 1128 // Generate a new block based on side chain 1129 newBlocks, _ := GenerateChain(params.TestChainConfig, sideChain[len(sideChain)-1], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) 1130 go listenNewLog(logsCh, 1) 1131 if _, err := blockchain.InsertChain(newBlocks); err != nil { 1132 t.Fatalf("failed to insert forked chain: %v", err) 1133 } 1134 // Rebirth logs should omit a newLogEvent 1135 if !<-newLogCh { 1136 t.Fatalf("failed to receive new log event") 1137 } 1138 } 1139 1140 func TestReorgSideEvent(t *testing.T) { 1141 var ( 1142 db = ethdb.NewMemDatabase() 1143 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1144 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1145 gspec = &Genesis{ 1146 Config: params.TestChainConfig, 1147 Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}, 1148 } 1149 genesis = gspec.MustCommit(db) 1150 signer = types.NewEIP155Signer(gspec.Config.ChainID) 1151 ) 1152 1153 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1154 defer blockchain.Stop() 1155 1156 chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 1157 if _, err := blockchain.InsertChain(chain); err != nil { 1158 t.Fatalf("failed to insert chain: %v", err) 1159 } 1160 1161 replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) { 1162 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), nil), signer, key1) 1163 if i == 2 { 1164 gen.OffsetTime(-9) 1165 } 1166 if err != nil { 1167 t.Fatalf("failed to create tx: %v", err) 1168 } 1169 gen.AddTx(tx) 1170 }) 1171 chainSideCh := make(chan ChainSideEvent, 64) 1172 blockchain.SubscribeChainSideEvent(chainSideCh) 1173 if _, err := blockchain.InsertChain(replacementBlocks); err != nil { 1174 t.Fatalf("failed to insert chain: %v", err) 1175 } 1176 1177 // first two block of the secondary chain are for a brief moment considered 1178 // side chains because up to that point the first one is considered the 1179 // heavier chain. 1180 expectedSideHashes := map[common.Hash]bool{ 1181 replacementBlocks[0].Hash(): true, 1182 replacementBlocks[1].Hash(): true, 1183 chain[0].Hash(): true, 1184 chain[1].Hash(): true, 1185 chain[2].Hash(): true, 1186 } 1187 1188 i := 0 1189 1190 const timeoutDura = 10 * time.Second 1191 timeout := time.NewTimer(timeoutDura) 1192 done: 1193 for { 1194 select { 1195 case ev := <-chainSideCh: 1196 block := ev.Block 1197 if _, ok := expectedSideHashes[block.Hash()]; !ok { 1198 t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash()) 1199 } 1200 i++ 1201 1202 if i == len(expectedSideHashes) { 1203 timeout.Stop() 1204 1205 break done 1206 } 1207 timeout.Reset(timeoutDura) 1208 1209 case <-timeout.C: 1210 t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent") 1211 } 1212 } 1213 1214 // make sure no more events are fired 1215 select { 1216 case e := <-chainSideCh: 1217 t.Errorf("unexpected event fired: %v", e) 1218 case <-time.After(250 * time.Millisecond): 1219 } 1220 1221 } 1222 1223 // Tests if the canonical block can be fetched from the database during chain insertion. 1224 func TestCanonicalBlockRetrieval(t *testing.T) { 1225 _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) 1226 if err != nil { 1227 t.Fatalf("failed to create pristine chain: %v", err) 1228 } 1229 defer blockchain.Stop() 1230 1231 chain, _ := GenerateChain(blockchain.chainConfig, blockchain.genesisBlock, ethash.NewFaker(), blockchain.db, 10, func(i int, gen *BlockGen) {}) 1232 1233 var pend sync.WaitGroup 1234 pend.Add(len(chain)) 1235 1236 for i := range chain { 1237 go func(block *types.Block) { 1238 defer pend.Done() 1239 1240 // try to retrieve a block by its canonical hash and see if the block data can be retrieved. 1241 for { 1242 ch := rawdb.ReadCanonicalHash(blockchain.db, block.NumberU64()) 1243 if ch == (common.Hash{}) { 1244 continue // busy wait for canonical hash to be written 1245 } 1246 if ch != block.Hash() { 1247 t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex()) 1248 } 1249 fb := rawdb.ReadBlock(blockchain.db, ch, block.NumberU64()) 1250 if fb == nil { 1251 t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex()) 1252 } 1253 if fb.Hash() != block.Hash() { 1254 t.Fatalf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex()) 1255 } 1256 return 1257 } 1258 }(chain[i]) 1259 1260 if _, err := blockchain.InsertChain(types.Blocks{chain[i]}); err != nil { 1261 t.Fatalf("failed to insert block %d: %v", i, err) 1262 } 1263 } 1264 pend.Wait() 1265 } 1266 1267 func TestEIP155Transition(t *testing.T) { 1268 // Configure and generate a sample block chain 1269 var ( 1270 db = ethdb.NewMemDatabase() 1271 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1272 address = crypto.PubkeyToAddress(key.PublicKey) 1273 funds = big.NewInt(1000000000) 1274 deleteAddr = common.Address{1} 1275 gspec = &Genesis{ 1276 Config: ¶ms.ChainConfig{ChainID: big.NewInt(1), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}, 1277 Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, 1278 } 1279 genesis = gspec.MustCommit(db) 1280 ) 1281 1282 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1283 defer blockchain.Stop() 1284 1285 blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1286 var ( 1287 tx *types.Transaction 1288 err error 1289 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1290 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1291 } 1292 ) 1293 switch i { 1294 case 0: 1295 tx, err = basicTx(types.HomesteadSigner{}) 1296 if err != nil { 1297 t.Fatal(err) 1298 } 1299 block.AddTx(tx) 1300 case 2: 1301 tx, err = basicTx(types.HomesteadSigner{}) 1302 if err != nil { 1303 t.Fatal(err) 1304 } 1305 block.AddTx(tx) 1306 1307 tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainID)) 1308 if err != nil { 1309 t.Fatal(err) 1310 } 1311 block.AddTx(tx) 1312 case 3: 1313 tx, err = basicTx(types.HomesteadSigner{}) 1314 if err != nil { 1315 t.Fatal(err) 1316 } 1317 block.AddTx(tx) 1318 1319 tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainID)) 1320 if err != nil { 1321 t.Fatal(err) 1322 } 1323 block.AddTx(tx) 1324 } 1325 }) 1326 1327 if _, err := blockchain.InsertChain(blocks); err != nil { 1328 t.Fatal(err) 1329 } 1330 block := blockchain.GetBlockByNumber(1) 1331 if block.Transactions()[0].Protected() { 1332 t.Error("Expected block[0].txs[0] to not be replay protected") 1333 } 1334 1335 block = blockchain.GetBlockByNumber(3) 1336 if block.Transactions()[0].Protected() { 1337 t.Error("Expected block[3].txs[0] to not be replay protected") 1338 } 1339 if !block.Transactions()[1].Protected() { 1340 t.Error("Expected block[3].txs[1] to be replay protected") 1341 } 1342 if _, err := blockchain.InsertChain(blocks[4:]); err != nil { 1343 t.Fatal(err) 1344 } 1345 1346 // generate an invalid chain id transaction 1347 config := ¶ms.ChainConfig{ChainID: big.NewInt(2), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)} 1348 blocks, _ = GenerateChain(config, blocks[len(blocks)-1], ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1349 var ( 1350 tx *types.Transaction 1351 err error 1352 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1353 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1354 } 1355 ) 1356 if i == 0 { 1357 tx, err = basicTx(types.NewEIP155Signer(big.NewInt(2))) 1358 if err != nil { 1359 t.Fatal(err) 1360 } 1361 block.AddTx(tx) 1362 } 1363 }) 1364 _, err := blockchain.InsertChain(blocks) 1365 if err != types.ErrInvalidChainId { 1366 t.Error("expected error:", types.ErrInvalidChainId) 1367 } 1368 } 1369 1370 func TestEIP161AccountRemoval(t *testing.T) { 1371 // Configure and generate a sample block chain 1372 var ( 1373 db = ethdb.NewMemDatabase() 1374 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1375 address = crypto.PubkeyToAddress(key.PublicKey) 1376 funds = big.NewInt(1000000000) 1377 theAddr = common.Address{1} 1378 gspec = &Genesis{ 1379 Config: ¶ms.ChainConfig{ 1380 ChainID: big.NewInt(1), 1381 HomesteadBlock: new(big.Int), 1382 EIP155Block: new(big.Int), 1383 EIP158Block: big.NewInt(2), 1384 }, 1385 Alloc: GenesisAlloc{address: {Balance: funds}}, 1386 } 1387 genesis = gspec.MustCommit(db) 1388 ) 1389 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1390 defer blockchain.Stop() 1391 1392 blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, block *BlockGen) { 1393 var ( 1394 tx *types.Transaction 1395 err error 1396 signer = types.NewEIP155Signer(gspec.Config.ChainID) 1397 ) 1398 switch i { 1399 case 0: 1400 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1401 case 1: 1402 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1403 case 2: 1404 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1405 } 1406 if err != nil { 1407 t.Fatal(err) 1408 } 1409 block.AddTx(tx) 1410 }) 1411 // account must exist pre eip 161 1412 if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { 1413 t.Fatal(err) 1414 } 1415 if st, _ := blockchain.State(); !st.Exist(theAddr) { 1416 t.Error("expected account to exist") 1417 } 1418 1419 // account needs to be deleted post eip 161 1420 if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil { 1421 t.Fatal(err) 1422 } 1423 if st, _ := blockchain.State(); st.Exist(theAddr) { 1424 t.Error("account should not exist") 1425 } 1426 1427 // account musn't be created post eip 161 1428 if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil { 1429 t.Fatal(err) 1430 } 1431 if st, _ := blockchain.State(); st.Exist(theAddr) { 1432 t.Error("account should not exist") 1433 } 1434 } 1435 1436 // This is a regression test (i.e. as weird as it is, don't delete it ever), which 1437 // tests that under weird reorg conditions the blockchain and its internal header- 1438 // chain return the same latest block/header. 1439 // 1440 // https://github.com/ethereum/go-ethereum/pull/15941 1441 func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { 1442 // Generate a canonical chain to act as the main dataset 1443 engine := ethash.NewFaker() 1444 1445 db := ethdb.NewMemDatabase() 1446 genesis := new(Genesis).MustCommit(db) 1447 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1448 1449 // Generate a bunch of fork blocks, each side forking from the canonical chain 1450 forks := make([]*types.Block, len(blocks)) 1451 for i := 0; i < len(forks); i++ { 1452 parent := genesis 1453 if i > 0 { 1454 parent = blocks[i-1] 1455 } 1456 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1457 forks[i] = fork[0] 1458 } 1459 // Import the canonical and fork chain side by side, verifying the current block 1460 // and current header consistency 1461 diskdb := ethdb.NewMemDatabase() 1462 new(Genesis).MustCommit(diskdb) 1463 1464 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1465 if err != nil { 1466 t.Fatalf("failed to create tester chain: %v", err) 1467 } 1468 for i := 0; i < len(blocks); i++ { 1469 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1470 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1471 } 1472 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1473 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]) 1474 } 1475 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1476 t.Fatalf(" fork %d: failed to insert into chain: %v", i, err) 1477 } 1478 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1479 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]) 1480 } 1481 } 1482 } 1483 1484 // Tests that importing small side forks doesn't leave junk in the trie database 1485 // cache (which would eventually cause memory issues). 1486 func TestTrieForkGC(t *testing.T) { 1487 // Generate a canonical chain to act as the main dataset 1488 engine := ethash.NewFaker() 1489 1490 db := ethdb.NewMemDatabase() 1491 genesis := new(Genesis).MustCommit(db) 1492 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1493 1494 // Generate a bunch of fork blocks, each side forking from the canonical chain 1495 forks := make([]*types.Block, len(blocks)) 1496 for i := 0; i < len(forks); i++ { 1497 parent := genesis 1498 if i > 0 { 1499 parent = blocks[i-1] 1500 } 1501 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1502 forks[i] = fork[0] 1503 } 1504 // Import the canonical and fork chain side by side, forcing the trie cache to cache both 1505 diskdb := ethdb.NewMemDatabase() 1506 new(Genesis).MustCommit(diskdb) 1507 1508 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1509 if err != nil { 1510 t.Fatalf("failed to create tester chain: %v", err) 1511 } 1512 for i := 0; i < len(blocks); i++ { 1513 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1514 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1515 } 1516 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1517 t.Fatalf("fork %d: failed to insert into chain: %v", i, err) 1518 } 1519 } 1520 // Dereference all the recent tries and ensure no past trie is left in 1521 for i := 0; i < triesInMemory; i++ { 1522 chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root()) 1523 chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root()) 1524 } 1525 if len(chain.stateCache.TrieDB().Nodes()) > 0 { 1526 t.Fatalf("stale tries still alive after garbase collection") 1527 } 1528 } 1529 1530 // Tests that doing large reorgs works even if the state associated with the 1531 // forking point is not available any more. 1532 func TestLargeReorgTrieGC(t *testing.T) { 1533 // Generate the original common chain segment and the two competing forks 1534 engine := ethash.NewFaker() 1535 1536 db := ethdb.NewMemDatabase() 1537 genesis := new(Genesis).MustCommit(db) 1538 1539 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1540 original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1541 competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) 1542 1543 // Import the shared chain and the original canonical one 1544 diskdb := ethdb.NewMemDatabase() 1545 new(Genesis).MustCommit(diskdb) 1546 1547 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1548 if err != nil { 1549 t.Fatalf("failed to create tester chain: %v", err) 1550 } 1551 if _, err := chain.InsertChain(shared); err != nil { 1552 t.Fatalf("failed to insert shared chain: %v", err) 1553 } 1554 if _, err := chain.InsertChain(original); err != nil { 1555 t.Fatalf("failed to insert original chain: %v", err) 1556 } 1557 // Ensure that the state associated with the forking point is pruned away 1558 if node, _ := chain.stateCache.TrieDB().Node(shared[len(shared)-1].Root()); node != nil { 1559 t.Fatalf("common-but-old ancestor still cache") 1560 } 1561 // Import the competitor chain without exceeding the canonical's TD and ensure 1562 // we have not processed any of the blocks (protection against malicious blocks) 1563 if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil { 1564 t.Fatalf("failed to insert competitor chain: %v", err) 1565 } 1566 for i, block := range competitor[:len(competitor)-2] { 1567 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1568 t.Fatalf("competitor %d: low TD chain became processed", i) 1569 } 1570 } 1571 // Import the head of the competitor chain, triggering the reorg and ensure we 1572 // successfully reprocess all the stashed away blocks. 1573 if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil { 1574 t.Fatalf("failed to finalize competitor chain: %v", err) 1575 } 1576 for i, block := range competitor[:len(competitor)-triesInMemory] { 1577 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1578 t.Fatalf("competitor %d: competing chain state missing", i) 1579 } 1580 } 1581 } 1582 1583 // Benchmarks large blocks with value transfers to non-existing accounts 1584 func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) { 1585 var ( 1586 signer = types.HomesteadSigner{} 1587 testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1588 testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) 1589 bankFunds = big.NewInt(100000000000000000) 1590 gspec = Genesis{ 1591 Config: params.TestChainConfig, 1592 Alloc: GenesisAlloc{ 1593 testBankAddress: {Balance: bankFunds}, 1594 common.HexToAddress("0xc0de"): { 1595 Code: []byte{0x60, 0x01, 0x50}, 1596 Balance: big.NewInt(0), 1597 }, // push 1, pop 1598 }, 1599 GasLimit: 100e6, // 100 M 1600 } 1601 ) 1602 // Generate the original common chain segment and the two competing forks 1603 engine := ethash.NewFaker() 1604 db := ethdb.NewMemDatabase() 1605 genesis := gspec.MustCommit(db) 1606 1607 blockGenerator := func(i int, block *BlockGen) { 1608 block.SetCoinbase(common.Address{1}) 1609 for txi := 0; txi < numTxs; txi++ { 1610 uniq := uint64(i*numTxs + txi) 1611 recipient := recipientFn(uniq) 1612 //recipient := common.BigToAddress(big.NewInt(0).SetUint64(1337 + uniq)) 1613 tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxGas, big.NewInt(1), nil), signer, testBankKey) 1614 if err != nil { 1615 b.Error(err) 1616 } 1617 block.AddTx(tx) 1618 } 1619 } 1620 1621 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, numBlocks, blockGenerator) 1622 b.StopTimer() 1623 b.ResetTimer() 1624 for i := 0; i < b.N; i++ { 1625 // Import the shared chain and the original canonical one 1626 diskdb := ethdb.NewMemDatabase() 1627 gspec.MustCommit(diskdb) 1628 1629 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1630 if err != nil { 1631 b.Fatalf("failed to create tester chain: %v", err) 1632 } 1633 b.StartTimer() 1634 if _, err := chain.InsertChain(shared); err != nil { 1635 b.Fatalf("failed to insert shared chain: %v", err) 1636 } 1637 b.StopTimer() 1638 if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks { 1639 b.Fatalf("Transactions were not included, expected %d, got %d", (numTxs * numBlocks), got) 1640 1641 } 1642 } 1643 } 1644 func BenchmarkBlockChain_1x1000ValueTransferToNonexisting(b *testing.B) { 1645 var ( 1646 numTxs = 1000 1647 numBlocks = 1 1648 ) 1649 1650 recipientFn := func(nonce uint64) common.Address { 1651 return common.BigToAddress(big.NewInt(0).SetUint64(1337 + nonce)) 1652 } 1653 dataFn := func(nonce uint64) []byte { 1654 return nil 1655 } 1656 1657 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1658 } 1659 func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) { 1660 var ( 1661 numTxs = 1000 1662 numBlocks = 1 1663 ) 1664 b.StopTimer() 1665 b.ResetTimer() 1666 1667 recipientFn := func(nonce uint64) common.Address { 1668 return common.BigToAddress(big.NewInt(0).SetUint64(1337)) 1669 } 1670 dataFn := func(nonce uint64) []byte { 1671 return nil 1672 } 1673 1674 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1675 } 1676 func BenchmarkBlockChain_1x1000Executions(b *testing.B) { 1677 var ( 1678 numTxs = 1000 1679 numBlocks = 1 1680 ) 1681 b.StopTimer() 1682 b.ResetTimer() 1683 1684 recipientFn := func(nonce uint64) common.Address { 1685 return common.BigToAddress(big.NewInt(0).SetUint64(0xc0de)) 1686 } 1687 dataFn := func(nonce uint64) []byte { 1688 return nil 1689 } 1690 1691 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 1692 } 1693 1694 // Tests that importing a very large side fork, which is larger than the canon chain, 1695 // but where the difficulty per block is kept low: this means that it will not 1696 // overtake the 'canon' chain until after it's passed canon by about 200 blocks. 1697 // 1698 // Details at: 1699 // - https://github.com/ethereum/go-ethereum/issues/18977 1700 // - https://github.com/ethereum/go-ethereum/pull/18988 1701 func TestLowDiffLongChain(t *testing.T) { 1702 // Generate a canonical chain to act as the main dataset 1703 engine := ethash.NewFaker() 1704 db := ethdb.NewMemDatabase() 1705 genesis := new(Genesis).MustCommit(db) 1706 1707 // We must use a pretty long chain to ensure that the fork doesn't overtake us 1708 // until after at least 128 blocks post tip 1709 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 6*triesInMemory, func(i int, b *BlockGen) { 1710 b.SetCoinbase(common.Address{1}) 1711 b.OffsetTime(-9) 1712 }) 1713 1714 // Import the canonical chain 1715 diskdb := ethdb.NewMemDatabase() 1716 new(Genesis).MustCommit(diskdb) 1717 1718 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1719 if err != nil { 1720 t.Fatalf("failed to create tester chain: %v", err) 1721 } 1722 if n, err := chain.InsertChain(blocks); err != nil { 1723 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 1724 } 1725 // Generate fork chain, starting from an early block 1726 parent := blocks[10] 1727 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 8*triesInMemory, func(i int, b *BlockGen) { 1728 b.SetCoinbase(common.Address{2}) 1729 }) 1730 1731 // And now import the fork 1732 if i, err := chain.InsertChain(fork); err != nil { 1733 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1734 } 1735 head := chain.CurrentBlock() 1736 if got := fork[len(fork)-1].Hash(); got != head.Hash() { 1737 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 1738 } 1739 // Sanity check that all the canonical numbers are present 1740 header := chain.CurrentHeader() 1741 for number := head.NumberU64(); number > 0; number-- { 1742 if hash := chain.GetHeaderByNumber(number).Hash(); hash != header.Hash() { 1743 t.Fatalf("header %d: canonical hash mismatch: have %x, want %x", number, hash, header.Hash()) 1744 } 1745 header = chain.GetHeader(header.ParentHash, number-1) 1746 } 1747 }