github.com/mapprotocol/go-ethereum@v1.9.7/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 "io/ioutil" 22 "math/big" 23 "math/rand" 24 "os" 25 "sync" 26 "testing" 27 "time" 28 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/consensus" 31 "github.com/ethereum/go-ethereum/consensus/ethash" 32 "github.com/ethereum/go-ethereum/core/rawdb" 33 "github.com/ethereum/go-ethereum/core/state" 34 "github.com/ethereum/go-ethereum/core/types" 35 "github.com/ethereum/go-ethereum/core/vm" 36 "github.com/ethereum/go-ethereum/crypto" 37 "github.com/ethereum/go-ethereum/ethdb" 38 "github.com/ethereum/go-ethereum/params" 39 ) 40 41 // So we can deterministically seed different blockchains 42 var ( 43 canonicalSeed = 1 44 forkSeed = 2 45 ) 46 47 // newCanonical creates a chain database, and injects a deterministic canonical 48 // chain. Depending on the full flag, if creates either a full block chain or a 49 // header only chain. 50 func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *BlockChain, error) { 51 var ( 52 db = rawdb.NewMemoryDatabase() 53 genesis = new(Genesis).MustCommit(db) 54 ) 55 56 // Initialize a fresh chain with only a genesis block 57 blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil) 58 // Create and inject the requested chain 59 if n == 0 { 60 return db, blockchain, nil 61 } 62 if full { 63 // Full block-chain requested 64 blocks := makeBlockChain(genesis, n, engine, db, canonicalSeed) 65 _, err := blockchain.InsertChain(blocks) 66 return db, blockchain, err 67 } 68 // Header-only chain requested 69 headers := makeHeaderChain(genesis.Header(), n, engine, db, canonicalSeed) 70 _, err := blockchain.InsertHeaderChain(headers, 1) 71 return db, blockchain, err 72 } 73 74 // Test fork of length N starting from block i 75 func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) { 76 // Copy old chain up to #i into a new db 77 db, blockchain2, err := newCanonical(ethash.NewFaker(), i, full) 78 if err != nil { 79 t.Fatal("could not make new canonical in testFork", err) 80 } 81 defer blockchain2.Stop() 82 83 // Assert the chains have the same header/block at #i 84 var hash1, hash2 common.Hash 85 if full { 86 hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash() 87 hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash() 88 } else { 89 hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash() 90 hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash() 91 } 92 if hash1 != hash2 { 93 t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) 94 } 95 // Extend the newly created chain 96 var ( 97 blockChainB []*types.Block 98 headerChainB []*types.Header 99 ) 100 if full { 101 blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed) 102 if _, err := blockchain2.InsertChain(blockChainB); err != nil { 103 t.Fatalf("failed to insert forking chain: %v", err) 104 } 105 } else { 106 headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, ethash.NewFaker(), db, forkSeed) 107 if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil { 108 t.Fatalf("failed to insert forking chain: %v", err) 109 } 110 } 111 // Sanity check that the forked chain can be imported into the original 112 var tdPre, tdPost *big.Int 113 114 if full { 115 tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()) 116 if err := testBlockChainImport(blockChainB, blockchain); err != nil { 117 t.Fatalf("failed to import forked block chain: %v", err) 118 } 119 tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash()) 120 } else { 121 tdPre = blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()) 122 if err := testHeaderChainImport(headerChainB, blockchain); err != nil { 123 t.Fatalf("failed to import forked header chain: %v", err) 124 } 125 tdPost = blockchain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash()) 126 } 127 // Compare the total difficulties of the chains 128 comparator(tdPre, tdPost) 129 } 130 131 // testBlockChainImport tries to process a chain of blocks, writing them into 132 // the database if successful. 133 func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { 134 for _, block := range chain { 135 // Try and process the block 136 err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) 137 if err == nil { 138 err = blockchain.validator.ValidateBody(block) 139 } 140 if err != nil { 141 if err == ErrKnownBlock { 142 continue 143 } 144 return err 145 } 146 statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache) 147 if err != nil { 148 return err 149 } 150 receipts, _, usedGas, err := blockchain.processor.Process(block, statedb, vm.Config{}) 151 if err != nil { 152 blockchain.reportBlock(block, receipts, err) 153 return err 154 } 155 err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas) 156 if err != nil { 157 blockchain.reportBlock(block, receipts, err) 158 return err 159 } 160 blockchain.chainmu.Lock() 161 rawdb.WriteTd(blockchain.db, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash()))) 162 rawdb.WriteBlock(blockchain.db, block) 163 statedb.Commit(false) 164 blockchain.chainmu.Unlock() 165 } 166 return nil 167 } 168 169 // testHeaderChainImport tries to process a chain of header, writing them into 170 // the database if successful. 171 func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { 172 for _, header := range chain { 173 // Try and validate the header 174 if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil { 175 return err 176 } 177 // Manually insert the header into the database, but don't reorganise (allows subsequent testing) 178 blockchain.chainmu.Lock() 179 rawdb.WriteTd(blockchain.db, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash))) 180 rawdb.WriteHeader(blockchain.db, header) 181 blockchain.chainmu.Unlock() 182 } 183 return nil 184 } 185 186 func TestLastBlock(t *testing.T) { 187 _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) 188 if err != nil { 189 t.Fatalf("failed to create pristine chain: %v", err) 190 } 191 defer blockchain.Stop() 192 193 blocks := makeBlockChain(blockchain.CurrentBlock(), 1, ethash.NewFullFaker(), blockchain.db, 0) 194 if _, err := blockchain.InsertChain(blocks); err != nil { 195 t.Fatalf("Failed to insert block: %v", err) 196 } 197 if blocks[len(blocks)-1].Hash() != rawdb.ReadHeadBlockHash(blockchain.db) { 198 t.Fatalf("Write/Get HeadBlockHash failed") 199 } 200 } 201 202 // Tests that given a starting canonical chain of a given size, it can be extended 203 // with various length chains. 204 func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) } 205 func TestExtendCanonicalBlocks(t *testing.T) { testExtendCanonical(t, true) } 206 207 func testExtendCanonical(t *testing.T, full bool) { 208 length := 5 209 210 // Make first chain starting from genesis 211 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 212 if err != nil { 213 t.Fatalf("failed to make new canonical chain: %v", err) 214 } 215 defer processor.Stop() 216 217 // Define the difficulty comparator 218 better := func(td1, td2 *big.Int) { 219 if td2.Cmp(td1) <= 0 { 220 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 221 } 222 } 223 // Start fork from current height 224 testFork(t, processor, length, 1, full, better) 225 testFork(t, processor, length, 2, full, better) 226 testFork(t, processor, length, 5, full, better) 227 testFork(t, processor, length, 10, full, better) 228 } 229 230 // Tests that given a starting canonical chain of a given size, creating shorter 231 // forks do not take canonical ownership. 232 func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) } 233 func TestShorterForkBlocks(t *testing.T) { testShorterFork(t, true) } 234 235 func testShorterFork(t *testing.T, full bool) { 236 length := 10 237 238 // Make first chain starting from genesis 239 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 240 if err != nil { 241 t.Fatalf("failed to make new canonical chain: %v", err) 242 } 243 defer processor.Stop() 244 245 // Define the difficulty comparator 246 worse := func(td1, td2 *big.Int) { 247 if td2.Cmp(td1) >= 0 { 248 t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) 249 } 250 } 251 // Sum of numbers must be less than `length` for this to be a shorter fork 252 testFork(t, processor, 0, 3, full, worse) 253 testFork(t, processor, 0, 7, full, worse) 254 testFork(t, processor, 1, 1, full, worse) 255 testFork(t, processor, 1, 7, full, worse) 256 testFork(t, processor, 5, 3, full, worse) 257 testFork(t, processor, 5, 4, full, worse) 258 } 259 260 // Tests that given a starting canonical chain of a given size, creating longer 261 // forks do take canonical ownership. 262 func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) } 263 func TestLongerForkBlocks(t *testing.T) { testLongerFork(t, true) } 264 265 func testLongerFork(t *testing.T, full bool) { 266 length := 10 267 268 // Make first chain starting from genesis 269 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 270 if err != nil { 271 t.Fatalf("failed to make new canonical chain: %v", err) 272 } 273 defer processor.Stop() 274 275 // Define the difficulty comparator 276 better := func(td1, td2 *big.Int) { 277 if td2.Cmp(td1) <= 0 { 278 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 279 } 280 } 281 // Sum of numbers must be greater than `length` for this to be a longer fork 282 testFork(t, processor, 0, 11, full, better) 283 testFork(t, processor, 0, 15, full, better) 284 testFork(t, processor, 1, 10, full, better) 285 testFork(t, processor, 1, 12, full, better) 286 testFork(t, processor, 5, 6, full, better) 287 testFork(t, processor, 5, 8, full, better) 288 } 289 290 // Tests that given a starting canonical chain of a given size, creating equal 291 // forks do take canonical ownership. 292 func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) } 293 func TestEqualForkBlocks(t *testing.T) { testEqualFork(t, true) } 294 295 func testEqualFork(t *testing.T, full bool) { 296 length := 10 297 298 // Make first chain starting from genesis 299 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 300 if err != nil { 301 t.Fatalf("failed to make new canonical chain: %v", err) 302 } 303 defer processor.Stop() 304 305 // Define the difficulty comparator 306 equal := func(td1, td2 *big.Int) { 307 if td2.Cmp(td1) != 0 { 308 t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) 309 } 310 } 311 // Sum of numbers must be equal to `length` for this to be an equal fork 312 testFork(t, processor, 0, 10, full, equal) 313 testFork(t, processor, 1, 9, full, equal) 314 testFork(t, processor, 2, 8, full, equal) 315 testFork(t, processor, 5, 5, full, equal) 316 testFork(t, processor, 6, 4, full, equal) 317 testFork(t, processor, 9, 1, full, equal) 318 } 319 320 // Tests that chains missing links do not get accepted by the processor. 321 func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) } 322 func TestBrokenBlockChain(t *testing.T) { testBrokenChain(t, true) } 323 324 func testBrokenChain(t *testing.T, full bool) { 325 // Make chain starting from genesis 326 db, blockchain, err := newCanonical(ethash.NewFaker(), 10, full) 327 if err != nil { 328 t.Fatalf("failed to make new canonical chain: %v", err) 329 } 330 defer blockchain.Stop() 331 332 // Create a forked chain, and try to insert with a missing link 333 if full { 334 chain := makeBlockChain(blockchain.CurrentBlock(), 5, ethash.NewFaker(), db, forkSeed)[1:] 335 if err := testBlockChainImport(chain, blockchain); err == nil { 336 t.Errorf("broken block chain not reported") 337 } 338 } else { 339 chain := makeHeaderChain(blockchain.CurrentHeader(), 5, ethash.NewFaker(), db, forkSeed)[1:] 340 if err := testHeaderChainImport(chain, blockchain); err == nil { 341 t.Errorf("broken header chain not reported") 342 } 343 } 344 } 345 346 // Tests that reorganising a long difficult chain after a short easy one 347 // overwrites the canonical numbers and links in the database. 348 func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) } 349 func TestReorgLongBlocks(t *testing.T) { testReorgLong(t, true) } 350 351 func testReorgLong(t *testing.T, full bool) { 352 testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280, full) 353 } 354 355 // Tests that reorganising a short difficult chain after a long easy one 356 // overwrites the canonical numbers and links in the database. 357 func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false) } 358 func TestReorgShortBlocks(t *testing.T) { testReorgShort(t, true) } 359 360 func testReorgShort(t *testing.T, full bool) { 361 // Create a long easy chain vs. a short heavy one. Due to difficulty adjustment 362 // we need a fairly long chain of blocks with different difficulties for a short 363 // one to become heavyer than a long one. The 96 is an empirical value. 364 easy := make([]int64, 96) 365 for i := 0; i < len(easy); i++ { 366 easy[i] = 60 367 } 368 diff := make([]int64, len(easy)-1) 369 for i := 0; i < len(diff); i++ { 370 diff[i] = -9 371 } 372 testReorg(t, easy, diff, 12615120, full) 373 } 374 375 func testReorg(t *testing.T, first, second []int64, td int64, full bool) { 376 // Create a pristine chain and database 377 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 378 if err != nil { 379 t.Fatalf("failed to create pristine chain: %v", err) 380 } 381 defer blockchain.Stop() 382 383 // Insert an easy and a difficult chain afterwards 384 easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db, len(first), func(i int, b *BlockGen) { 385 b.OffsetTime(first[i]) 386 }) 387 diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db, len(second), func(i int, b *BlockGen) { 388 b.OffsetTime(second[i]) 389 }) 390 if full { 391 if _, err := blockchain.InsertChain(easyBlocks); err != nil { 392 t.Fatalf("failed to insert easy chain: %v", err) 393 } 394 if _, err := blockchain.InsertChain(diffBlocks); err != nil { 395 t.Fatalf("failed to insert difficult chain: %v", err) 396 } 397 } else { 398 easyHeaders := make([]*types.Header, len(easyBlocks)) 399 for i, block := range easyBlocks { 400 easyHeaders[i] = block.Header() 401 } 402 diffHeaders := make([]*types.Header, len(diffBlocks)) 403 for i, block := range diffBlocks { 404 diffHeaders[i] = block.Header() 405 } 406 if _, err := blockchain.InsertHeaderChain(easyHeaders, 1); err != nil { 407 t.Fatalf("failed to insert easy chain: %v", err) 408 } 409 if _, err := blockchain.InsertHeaderChain(diffHeaders, 1); err != nil { 410 t.Fatalf("failed to insert difficult chain: %v", err) 411 } 412 } 413 // Check that the chain is valid number and link wise 414 if full { 415 prev := blockchain.CurrentBlock() 416 for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, blockchain.GetBlockByNumber(block.NumberU64()-1) { 417 if prev.ParentHash() != block.Hash() { 418 t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash(), block.Hash()) 419 } 420 } 421 } else { 422 prev := blockchain.CurrentHeader() 423 for header := blockchain.GetHeaderByNumber(blockchain.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, blockchain.GetHeaderByNumber(header.Number.Uint64()-1) { 424 if prev.ParentHash != header.Hash() { 425 t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash()) 426 } 427 } 428 } 429 // Make sure the chain total difficulty is the correct one 430 want := new(big.Int).Add(blockchain.genesisBlock.Difficulty(), big.NewInt(td)) 431 if full { 432 if have := blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()); have.Cmp(want) != 0 { 433 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 434 } 435 } else { 436 if have := blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()); have.Cmp(want) != 0 { 437 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 438 } 439 } 440 } 441 442 // Tests that the insertion functions detect banned hashes. 443 func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) } 444 func TestBadBlockHashes(t *testing.T) { testBadHashes(t, true) } 445 446 func testBadHashes(t *testing.T, full bool) { 447 // Create a pristine chain and database 448 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 449 if err != nil { 450 t.Fatalf("failed to create pristine chain: %v", err) 451 } 452 defer blockchain.Stop() 453 454 // Create a chain, ban a hash and try to import 455 if full { 456 blocks := makeBlockChain(blockchain.CurrentBlock(), 3, ethash.NewFaker(), db, 10) 457 458 BadHashes[blocks[2].Header().Hash()] = true 459 defer func() { delete(BadHashes, blocks[2].Header().Hash()) }() 460 461 _, err = blockchain.InsertChain(blocks) 462 } else { 463 headers := makeHeaderChain(blockchain.CurrentHeader(), 3, ethash.NewFaker(), db, 10) 464 465 BadHashes[headers[2].Hash()] = true 466 defer func() { delete(BadHashes, headers[2].Hash()) }() 467 468 _, err = blockchain.InsertHeaderChain(headers, 1) 469 } 470 if err != ErrBlacklistedHash { 471 t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash) 472 } 473 } 474 475 // Tests that bad hashes are detected on boot, and the chain rolled back to a 476 // good state prior to the bad hash. 477 func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) } 478 func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) } 479 480 func testReorgBadHashes(t *testing.T, full bool) { 481 // Create a pristine chain and database 482 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 483 if err != nil { 484 t.Fatalf("failed to create pristine chain: %v", err) 485 } 486 // Create a chain, import and ban afterwards 487 headers := makeHeaderChain(blockchain.CurrentHeader(), 4, ethash.NewFaker(), db, 10) 488 blocks := makeBlockChain(blockchain.CurrentBlock(), 4, ethash.NewFaker(), db, 10) 489 490 if full { 491 if _, err = blockchain.InsertChain(blocks); err != nil { 492 t.Errorf("failed to import blocks: %v", err) 493 } 494 if blockchain.CurrentBlock().Hash() != blocks[3].Hash() { 495 t.Errorf("last block hash mismatch: have: %x, want %x", blockchain.CurrentBlock().Hash(), blocks[3].Header().Hash()) 496 } 497 BadHashes[blocks[3].Header().Hash()] = true 498 defer func() { delete(BadHashes, blocks[3].Header().Hash()) }() 499 } else { 500 if _, err = blockchain.InsertHeaderChain(headers, 1); err != nil { 501 t.Errorf("failed to import headers: %v", err) 502 } 503 if blockchain.CurrentHeader().Hash() != headers[3].Hash() { 504 t.Errorf("last header hash mismatch: have: %x, want %x", blockchain.CurrentHeader().Hash(), headers[3].Hash()) 505 } 506 BadHashes[headers[3].Hash()] = true 507 defer func() { delete(BadHashes, headers[3].Hash()) }() 508 } 509 blockchain.Stop() 510 511 // Create a new BlockChain and check that it rolled back the state. 512 ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, ethash.NewFaker(), vm.Config{}, nil) 513 if err != nil { 514 t.Fatalf("failed to create new chain manager: %v", err) 515 } 516 if full { 517 if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() { 518 t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash()) 519 } 520 if blocks[2].Header().GasLimit != ncm.GasLimit() { 521 t.Errorf("last block gasLimit mismatch: have: %d, want %d", ncm.GasLimit(), blocks[2].Header().GasLimit) 522 } 523 } else { 524 if ncm.CurrentHeader().Hash() != headers[2].Hash() { 525 t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) 526 } 527 } 528 ncm.Stop() 529 } 530 531 // Tests chain insertions in the face of one entity containing an invalid nonce. 532 func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) } 533 func TestBlocksInsertNonceError(t *testing.T) { testInsertNonceError(t, true) } 534 535 func testInsertNonceError(t *testing.T, full bool) { 536 for i := 1; i < 25 && !t.Failed(); i++ { 537 // Create a pristine chain and database 538 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 539 if err != nil { 540 t.Fatalf("failed to create pristine chain: %v", err) 541 } 542 defer blockchain.Stop() 543 544 // Create and insert a chain with a failing nonce 545 var ( 546 failAt int 547 failRes int 548 failNum uint64 549 ) 550 if full { 551 blocks := makeBlockChain(blockchain.CurrentBlock(), i, ethash.NewFaker(), db, 0) 552 553 failAt = rand.Int() % len(blocks) 554 failNum = blocks[failAt].NumberU64() 555 556 blockchain.engine = ethash.NewFakeFailer(failNum) 557 failRes, err = blockchain.InsertChain(blocks) 558 } else { 559 headers := makeHeaderChain(blockchain.CurrentHeader(), i, ethash.NewFaker(), db, 0) 560 561 failAt = rand.Int() % len(headers) 562 failNum = headers[failAt].Number.Uint64() 563 564 blockchain.engine = ethash.NewFakeFailer(failNum) 565 blockchain.hc.engine = blockchain.engine 566 failRes, err = blockchain.InsertHeaderChain(headers, 1) 567 } 568 // Check that the returned error indicates the failure 569 if failRes != failAt { 570 t.Errorf("test %d: failure (%v) index mismatch: have %d, want %d", i, err, failRes, failAt) 571 } 572 // Check that all blocks after the failing block have been inserted 573 for j := 0; j < i-failAt; j++ { 574 if full { 575 if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil { 576 t.Errorf("test %d: invalid block in chain: %v", i, block) 577 } 578 } else { 579 if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil { 580 t.Errorf("test %d: invalid header in chain: %v", i, header) 581 } 582 } 583 } 584 } 585 } 586 587 // Tests that fast importing a block chain produces the same chain data as the 588 // classical full block processing. 589 func TestFastVsFullChains(t *testing.T) { 590 // Configure and generate a sample block chain 591 var ( 592 gendb = rawdb.NewMemoryDatabase() 593 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 594 address = crypto.PubkeyToAddress(key.PublicKey) 595 funds = big.NewInt(1000000000) 596 gspec = &Genesis{ 597 Config: params.TestChainConfig, 598 Alloc: GenesisAlloc{address: {Balance: funds}}, 599 } 600 genesis = gspec.MustCommit(gendb) 601 signer = types.NewEIP155Signer(gspec.Config.ChainID) 602 ) 603 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, 1024, func(i int, block *BlockGen) { 604 block.SetCoinbase(common.Address{0x00}) 605 606 // If the block number is multiple of 3, send a few bonus transactions to the miner 607 if i%3 == 2 { 608 for j := 0; j < i%4+1; j++ { 609 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key) 610 if err != nil { 611 panic(err) 612 } 613 block.AddTx(tx) 614 } 615 } 616 // If the block number is a multiple of 5, add a few bonus uncles to the block 617 if i%5 == 5 { 618 block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))}) 619 } 620 }) 621 // Import the chain as an archive node for the comparison baseline 622 archiveDb := rawdb.NewMemoryDatabase() 623 gspec.MustCommit(archiveDb) 624 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 625 defer archive.Stop() 626 627 if n, err := archive.InsertChain(blocks); err != nil { 628 t.Fatalf("failed to process block %d: %v", n, err) 629 } 630 // Fast import the chain as a non-archive node to test 631 fastDb := rawdb.NewMemoryDatabase() 632 gspec.MustCommit(fastDb) 633 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 634 defer fast.Stop() 635 636 headers := make([]*types.Header, len(blocks)) 637 for i, block := range blocks { 638 headers[i] = block.Header() 639 } 640 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 641 t.Fatalf("failed to insert header %d: %v", n, err) 642 } 643 if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil { 644 t.Fatalf("failed to insert receipt %d: %v", n, err) 645 } 646 // Freezer style fast import the chain. 647 frdir, err := ioutil.TempDir("", "") 648 if err != nil { 649 t.Fatalf("failed to create temp freezer dir: %v", err) 650 } 651 defer os.Remove(frdir) 652 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "") 653 if err != nil { 654 t.Fatalf("failed to create temp freezer db: %v", err) 655 } 656 gspec.MustCommit(ancientDb) 657 ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 658 defer ancient.Stop() 659 660 if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { 661 t.Fatalf("failed to insert header %d: %v", n, err) 662 } 663 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(len(blocks)/2)); err != nil { 664 t.Fatalf("failed to insert receipt %d: %v", n, err) 665 } 666 // Iterate over all chain data components, and cross reference 667 for i := 0; i < len(blocks); i++ { 668 num, hash := blocks[i].NumberU64(), blocks[i].Hash() 669 670 if ftd, atd := fast.GetTdByHash(hash), archive.GetTdByHash(hash); ftd.Cmp(atd) != 0 { 671 t.Errorf("block #%d [%x]: td mismatch: fastdb %v, archivedb %v", num, hash, ftd, atd) 672 } 673 if antd, artd := ancient.GetTdByHash(hash), archive.GetTdByHash(hash); antd.Cmp(artd) != 0 { 674 t.Errorf("block #%d [%x]: td mismatch: ancientdb %v, archivedb %v", num, hash, antd, artd) 675 } 676 if fheader, aheader := fast.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); fheader.Hash() != aheader.Hash() { 677 t.Errorf("block #%d [%x]: header mismatch: fastdb %v, archivedb %v", num, hash, fheader, aheader) 678 } 679 if anheader, arheader := ancient.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); anheader.Hash() != arheader.Hash() { 680 t.Errorf("block #%d [%x]: header mismatch: ancientdb %v, archivedb %v", num, hash, anheader, arheader) 681 } 682 if fblock, arblock, anblock := fast.GetBlockByHash(hash), archive.GetBlockByHash(hash), ancient.GetBlockByHash(hash); fblock.Hash() != arblock.Hash() || anblock.Hash() != arblock.Hash() { 683 t.Errorf("block #%d [%x]: block mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, fblock, anblock, arblock) 684 } else if types.DeriveSha(fblock.Transactions()) != types.DeriveSha(arblock.Transactions()) || types.DeriveSha(anblock.Transactions()) != types.DeriveSha(arblock.Transactions()) { 685 t.Errorf("block #%d [%x]: transactions mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, fblock.Transactions(), anblock.Transactions(), arblock.Transactions()) 686 } else if types.CalcUncleHash(fblock.Uncles()) != types.CalcUncleHash(arblock.Uncles()) || types.CalcUncleHash(anblock.Uncles()) != types.CalcUncleHash(arblock.Uncles()) { 687 t.Errorf("block #%d [%x]: uncles mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, fblock.Uncles(), anblock, arblock.Uncles()) 688 } 689 if freceipts, anreceipts, areceipts := rawdb.ReadReceipts(fastDb, hash, *rawdb.ReadHeaderNumber(fastDb, hash), fast.Config()), rawdb.ReadReceipts(ancientDb, hash, *rawdb.ReadHeaderNumber(ancientDb, hash), fast.Config()), rawdb.ReadReceipts(archiveDb, hash, *rawdb.ReadHeaderNumber(archiveDb, hash), fast.Config()); types.DeriveSha(freceipts) != types.DeriveSha(areceipts) { 690 t.Errorf("block #%d [%x]: receipts mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, freceipts, anreceipts, areceipts) 691 } 692 } 693 // Check that the canonical chains are the same between the databases 694 for i := 0; i < len(blocks)+1; i++ { 695 if fhash, ahash := rawdb.ReadCanonicalHash(fastDb, uint64(i)), rawdb.ReadCanonicalHash(archiveDb, uint64(i)); fhash != ahash { 696 t.Errorf("block #%d: canonical hash mismatch: fastdb %v, archivedb %v", i, fhash, ahash) 697 } 698 if anhash, arhash := rawdb.ReadCanonicalHash(ancientDb, uint64(i)), rawdb.ReadCanonicalHash(archiveDb, uint64(i)); anhash != arhash { 699 t.Errorf("block #%d: canonical hash mismatch: ancientdb %v, archivedb %v", i, anhash, arhash) 700 } 701 } 702 } 703 704 // Tests that various import methods move the chain head pointers to the correct 705 // positions. 706 func TestLightVsFastVsFullChainHeads(t *testing.T) { 707 // Configure and generate a sample block chain 708 var ( 709 gendb = rawdb.NewMemoryDatabase() 710 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 711 address = crypto.PubkeyToAddress(key.PublicKey) 712 funds = big.NewInt(1000000000) 713 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 714 genesis = gspec.MustCommit(gendb) 715 ) 716 height := uint64(1024) 717 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil) 718 719 // makeDb creates a db instance for testing. 720 makeDb := func() (ethdb.Database, func()) { 721 dir, err := ioutil.TempDir("", "") 722 if err != nil { 723 t.Fatalf("failed to create temp freezer dir: %v", err) 724 } 725 defer os.Remove(dir) 726 db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), dir, "") 727 if err != nil { 728 t.Fatalf("failed to create temp freezer db: %v", err) 729 } 730 gspec.MustCommit(db) 731 return db, func() { os.RemoveAll(dir) } 732 } 733 // Configure a subchain to roll back 734 remove := []common.Hash{} 735 for _, block := range blocks[height/2:] { 736 remove = append(remove, block.Hash()) 737 } 738 // Create a small assertion method to check the three heads 739 assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { 740 if num := chain.CurrentBlock().NumberU64(); num != block { 741 t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) 742 } 743 if num := chain.CurrentFastBlock().NumberU64(); num != fast { 744 t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast) 745 } 746 if num := chain.CurrentHeader().Number.Uint64(); num != header { 747 t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header) 748 } 749 } 750 // Import the chain as an archive node and ensure all pointers are updated 751 archiveDb, delfn := makeDb() 752 defer delfn() 753 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 754 if n, err := archive.InsertChain(blocks); err != nil { 755 t.Fatalf("failed to process block %d: %v", n, err) 756 } 757 defer archive.Stop() 758 759 assert(t, "archive", archive, height, height, height) 760 archive.Rollback(remove) 761 assert(t, "archive", archive, height/2, height/2, height/2) 762 763 // Import the chain as a non-archive node and ensure all pointers are updated 764 fastDb, delfn := makeDb() 765 defer delfn() 766 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 767 defer fast.Stop() 768 769 headers := make([]*types.Header, len(blocks)) 770 for i, block := range blocks { 771 headers[i] = block.Header() 772 } 773 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 774 t.Fatalf("failed to insert header %d: %v", n, err) 775 } 776 if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil { 777 t.Fatalf("failed to insert receipt %d: %v", n, err) 778 } 779 assert(t, "fast", fast, height, height, 0) 780 fast.Rollback(remove) 781 assert(t, "fast", fast, height/2, height/2, 0) 782 783 // Import the chain as a ancient-first node and ensure all pointers are updated 784 ancientDb, delfn := makeDb() 785 defer delfn() 786 ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 787 defer ancient.Stop() 788 789 if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { 790 t.Fatalf("failed to insert header %d: %v", n, err) 791 } 792 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { 793 t.Fatalf("failed to insert receipt %d: %v", n, err) 794 } 795 assert(t, "ancient", ancient, height, height, 0) 796 ancient.Rollback(remove) 797 assert(t, "ancient", ancient, height/2, height/2, 0) 798 if frozen, err := ancientDb.Ancients(); err != nil || frozen != height/2+1 { 799 t.Fatalf("failed to truncate ancient store, want %v, have %v", height/2+1, frozen) 800 } 801 802 // Import the chain as a light node and ensure all pointers are updated 803 lightDb, delfn := makeDb() 804 defer delfn() 805 light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 806 if n, err := light.InsertHeaderChain(headers, 1); err != nil { 807 t.Fatalf("failed to insert header %d: %v", n, err) 808 } 809 defer light.Stop() 810 811 assert(t, "light", light, height, 0, 0) 812 light.Rollback(remove) 813 assert(t, "light", light, height/2, 0, 0) 814 } 815 816 // Tests that chain reorganisations handle transaction removals and reinsertions. 817 func TestChainTxReorgs(t *testing.T) { 818 var ( 819 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 820 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 821 key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 822 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 823 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 824 addr3 = crypto.PubkeyToAddress(key3.PublicKey) 825 db = rawdb.NewMemoryDatabase() 826 gspec = &Genesis{ 827 Config: params.TestChainConfig, 828 GasLimit: 3141592, 829 Alloc: GenesisAlloc{ 830 addr1: {Balance: big.NewInt(1000000)}, 831 addr2: {Balance: big.NewInt(1000000)}, 832 addr3: {Balance: big.NewInt(1000000)}, 833 }, 834 } 835 genesis = gspec.MustCommit(db) 836 signer = types.NewEIP155Signer(gspec.Config.ChainID) 837 ) 838 839 // Create two transactions shared between the chains: 840 // - postponed: transaction included at a later block in the forked chain 841 // - swapped: transaction included at the same block number in the forked chain 842 postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 843 swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 844 845 // Create two transactions that will be dropped by the forked chain: 846 // - pastDrop: transaction dropped retroactively from a past block 847 // - freshDrop: transaction dropped exactly at the block where the reorg is detected 848 var pastDrop, freshDrop *types.Transaction 849 850 // Create three transactions that will be added in the forked chain: 851 // - pastAdd: transaction added before the reorganization is detected 852 // - freshAdd: transaction added at the exact block the reorg is detected 853 // - futureAdd: transaction added after the reorg has already finished 854 var pastAdd, freshAdd, futureAdd *types.Transaction 855 856 chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) { 857 switch i { 858 case 0: 859 pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 860 861 gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point 862 gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork 863 864 case 2: 865 freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 866 867 gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point 868 gen.AddTx(swapped) // This transaction will be swapped out at the exact height 869 870 gen.OffsetTime(9) // Lower the block difficulty to simulate a weaker chain 871 } 872 }) 873 // Import the chain. This runs all block validation rules. 874 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 875 if i, err := blockchain.InsertChain(chain); err != nil { 876 t.Fatalf("failed to insert original chain[%d]: %v", i, err) 877 } 878 defer blockchain.Stop() 879 880 // overwrite the old chain 881 chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) { 882 switch i { 883 case 0: 884 pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 885 gen.AddTx(pastAdd) // This transaction needs to be injected during reorg 886 887 case 2: 888 gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain 889 gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain 890 891 freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 892 gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time 893 894 case 3: 895 futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 896 gen.AddTx(futureAdd) // This transaction will be added after a full reorg 897 } 898 }) 899 if _, err := blockchain.InsertChain(chain); err != nil { 900 t.Fatalf("failed to insert forked chain: %v", err) 901 } 902 903 // removed tx 904 for i, tx := range (types.Transactions{pastDrop, freshDrop}) { 905 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn != nil { 906 t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) 907 } 908 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt != nil { 909 t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt) 910 } 911 } 912 // added tx 913 for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) { 914 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 915 t.Errorf("add %d: expected tx to be found", i) 916 } 917 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt == nil { 918 t.Errorf("add %d: expected receipt to be found", i) 919 } 920 } 921 // shared tx 922 for i, tx := range (types.Transactions{postponed, swapped}) { 923 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 924 t.Errorf("share %d: expected tx to be found", i) 925 } 926 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt == nil { 927 t.Errorf("share %d: expected receipt to be found", i) 928 } 929 } 930 } 931 932 func TestLogReorgs(t *testing.T) { 933 var ( 934 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 935 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 936 db = rawdb.NewMemoryDatabase() 937 // this code generates a log 938 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 939 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 940 genesis = gspec.MustCommit(db) 941 signer = types.NewEIP155Signer(gspec.Config.ChainID) 942 ) 943 944 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 945 defer blockchain.Stop() 946 947 rmLogsCh := make(chan RemovedLogsEvent) 948 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 949 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 950 if i == 1 { 951 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 952 if err != nil { 953 t.Fatalf("failed to create tx: %v", err) 954 } 955 gen.AddTx(tx) 956 } 957 }) 958 if _, err := blockchain.InsertChain(chain); err != nil { 959 t.Fatalf("failed to insert chain: %v", err) 960 } 961 962 chain, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 963 if _, err := blockchain.InsertChain(chain); err != nil { 964 t.Fatalf("failed to insert forked chain: %v", err) 965 } 966 967 timeout := time.NewTimer(1 * time.Second) 968 select { 969 case ev := <-rmLogsCh: 970 if len(ev.Logs) == 0 { 971 t.Error("expected logs") 972 } 973 case <-timeout.C: 974 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 975 } 976 } 977 978 func TestLogRebirth(t *testing.T) { 979 var ( 980 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 981 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 982 db = rawdb.NewMemoryDatabase() 983 984 // this code generates a log 985 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 986 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 987 genesis = gspec.MustCommit(db) 988 signer = types.NewEIP155Signer(gspec.Config.ChainID) 989 newLogCh = make(chan bool) 990 ) 991 992 // listenNewLog checks whether the received logs number is equal with expected. 993 listenNewLog := func(sink chan []*types.Log, expect int) { 994 cnt := 0 995 for { 996 select { 997 case logs := <-sink: 998 cnt += len(logs) 999 case <-time.NewTimer(5 * time.Second).C: 1000 // new logs timeout 1001 newLogCh <- false 1002 return 1003 } 1004 if cnt == expect { 1005 break 1006 } else if cnt > expect { 1007 // redundant logs received 1008 newLogCh <- false 1009 return 1010 } 1011 } 1012 select { 1013 case <-sink: 1014 // redundant logs received 1015 newLogCh <- false 1016 case <-time.NewTimer(100 * time.Millisecond).C: 1017 newLogCh <- true 1018 } 1019 } 1020 1021 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1022 defer blockchain.Stop() 1023 1024 logsCh := make(chan []*types.Log) 1025 blockchain.SubscribeLogsEvent(logsCh) 1026 1027 rmLogsCh := make(chan RemovedLogsEvent) 1028 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 1029 1030 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1031 if i == 1 { 1032 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 1033 if err != nil { 1034 t.Fatalf("failed to create tx: %v", err) 1035 } 1036 gen.AddTx(tx) 1037 } 1038 }) 1039 1040 // Spawn a goroutine to receive log events 1041 go listenNewLog(logsCh, 1) 1042 if _, err := blockchain.InsertChain(chain); err != nil { 1043 t.Fatalf("failed to insert chain: %v", err) 1044 } 1045 if !<-newLogCh { 1046 t.Fatalf("failed to receive new log event") 1047 } 1048 1049 // Generate long reorg chain 1050 forkChain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1051 if i == 1 { 1052 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 1053 if err != nil { 1054 t.Fatalf("failed to create tx: %v", err) 1055 } 1056 gen.AddTx(tx) 1057 // Higher block difficulty 1058 gen.OffsetTime(-9) 1059 } 1060 }) 1061 1062 // Spawn a goroutine to receive log events 1063 go listenNewLog(logsCh, 1) 1064 if _, err := blockchain.InsertChain(forkChain); err != nil { 1065 t.Fatalf("failed to insert forked chain: %v", err) 1066 } 1067 if !<-newLogCh { 1068 t.Fatalf("failed to receive new log event") 1069 } 1070 // Ensure removedLog events received 1071 select { 1072 case ev := <-rmLogsCh: 1073 if len(ev.Logs) == 0 { 1074 t.Error("expected logs") 1075 } 1076 case <-time.NewTimer(1 * time.Second).C: 1077 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 1078 } 1079 1080 newBlocks, _ := GenerateChain(params.TestChainConfig, chain[len(chain)-1], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) 1081 go listenNewLog(logsCh, 1) 1082 if _, err := blockchain.InsertChain(newBlocks); err != nil { 1083 t.Fatalf("failed to insert forked chain: %v", err) 1084 } 1085 // Ensure removedLog events received 1086 select { 1087 case ev := <-rmLogsCh: 1088 if len(ev.Logs) == 0 { 1089 t.Error("expected logs") 1090 } 1091 case <-time.NewTimer(1 * time.Second).C: 1092 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 1093 } 1094 // Rebirth logs should omit a newLogEvent 1095 if !<-newLogCh { 1096 t.Fatalf("failed to receive new log event") 1097 } 1098 } 1099 1100 func TestSideLogRebirth(t *testing.T) { 1101 var ( 1102 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1103 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1104 db = rawdb.NewMemoryDatabase() 1105 1106 // this code generates a log 1107 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 1108 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 1109 genesis = gspec.MustCommit(db) 1110 signer = types.NewEIP155Signer(gspec.Config.ChainID) 1111 newLogCh = make(chan bool) 1112 ) 1113 1114 // listenNewLog checks whether the received logs number is equal with expected. 1115 listenNewLog := func(sink chan []*types.Log, expect int) { 1116 cnt := 0 1117 for { 1118 select { 1119 case logs := <-sink: 1120 cnt += len(logs) 1121 case <-time.NewTimer(5 * time.Second).C: 1122 // new logs timeout 1123 newLogCh <- false 1124 return 1125 } 1126 if cnt == expect { 1127 break 1128 } else if cnt > expect { 1129 // redundant logs received 1130 newLogCh <- false 1131 return 1132 } 1133 } 1134 select { 1135 case <-sink: 1136 // redundant logs received 1137 newLogCh <- false 1138 case <-time.NewTimer(100 * time.Millisecond).C: 1139 newLogCh <- true 1140 } 1141 } 1142 1143 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1144 defer blockchain.Stop() 1145 1146 logsCh := make(chan []*types.Log) 1147 blockchain.SubscribeLogsEvent(logsCh) 1148 1149 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1150 if i == 1 { 1151 // Higher block difficulty 1152 gen.OffsetTime(-9) 1153 } 1154 }) 1155 if _, err := blockchain.InsertChain(chain); err != nil { 1156 t.Fatalf("failed to insert forked chain: %v", err) 1157 } 1158 1159 // Generate side chain with lower difficulty 1160 sideChain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1161 if i == 1 { 1162 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 1163 if err != nil { 1164 t.Fatalf("failed to create tx: %v", err) 1165 } 1166 gen.AddTx(tx) 1167 } 1168 }) 1169 if _, err := blockchain.InsertChain(sideChain); err != nil { 1170 t.Fatalf("failed to insert forked chain: %v", err) 1171 } 1172 1173 // Generate a new block based on side chain 1174 newBlocks, _ := GenerateChain(params.TestChainConfig, sideChain[len(sideChain)-1], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) 1175 go listenNewLog(logsCh, 1) 1176 if _, err := blockchain.InsertChain(newBlocks); err != nil { 1177 t.Fatalf("failed to insert forked chain: %v", err) 1178 } 1179 // Rebirth logs should omit a newLogEvent 1180 if !<-newLogCh { 1181 t.Fatalf("failed to receive new log event") 1182 } 1183 } 1184 1185 func TestReorgSideEvent(t *testing.T) { 1186 var ( 1187 db = rawdb.NewMemoryDatabase() 1188 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1189 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1190 gspec = &Genesis{ 1191 Config: params.TestChainConfig, 1192 Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}, 1193 } 1194 genesis = gspec.MustCommit(db) 1195 signer = types.NewEIP155Signer(gspec.Config.ChainID) 1196 ) 1197 1198 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1199 defer blockchain.Stop() 1200 1201 chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 1202 if _, err := blockchain.InsertChain(chain); err != nil { 1203 t.Fatalf("failed to insert chain: %v", err) 1204 } 1205 1206 replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) { 1207 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), nil), signer, key1) 1208 if i == 2 { 1209 gen.OffsetTime(-9) 1210 } 1211 if err != nil { 1212 t.Fatalf("failed to create tx: %v", err) 1213 } 1214 gen.AddTx(tx) 1215 }) 1216 chainSideCh := make(chan ChainSideEvent, 64) 1217 blockchain.SubscribeChainSideEvent(chainSideCh) 1218 if _, err := blockchain.InsertChain(replacementBlocks); err != nil { 1219 t.Fatalf("failed to insert chain: %v", err) 1220 } 1221 1222 // first two block of the secondary chain are for a brief moment considered 1223 // side chains because up to that point the first one is considered the 1224 // heavier chain. 1225 expectedSideHashes := map[common.Hash]bool{ 1226 replacementBlocks[0].Hash(): true, 1227 replacementBlocks[1].Hash(): true, 1228 chain[0].Hash(): true, 1229 chain[1].Hash(): true, 1230 chain[2].Hash(): true, 1231 } 1232 1233 i := 0 1234 1235 const timeoutDura = 10 * time.Second 1236 timeout := time.NewTimer(timeoutDura) 1237 done: 1238 for { 1239 select { 1240 case ev := <-chainSideCh: 1241 block := ev.Block 1242 if _, ok := expectedSideHashes[block.Hash()]; !ok { 1243 t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash()) 1244 } 1245 i++ 1246 1247 if i == len(expectedSideHashes) { 1248 timeout.Stop() 1249 1250 break done 1251 } 1252 timeout.Reset(timeoutDura) 1253 1254 case <-timeout.C: 1255 t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent") 1256 } 1257 } 1258 1259 // make sure no more events are fired 1260 select { 1261 case e := <-chainSideCh: 1262 t.Errorf("unexpected event fired: %v", e) 1263 case <-time.After(250 * time.Millisecond): 1264 } 1265 1266 } 1267 1268 // Tests if the canonical block can be fetched from the database during chain insertion. 1269 func TestCanonicalBlockRetrieval(t *testing.T) { 1270 _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) 1271 if err != nil { 1272 t.Fatalf("failed to create pristine chain: %v", err) 1273 } 1274 defer blockchain.Stop() 1275 1276 chain, _ := GenerateChain(blockchain.chainConfig, blockchain.genesisBlock, ethash.NewFaker(), blockchain.db, 10, func(i int, gen *BlockGen) {}) 1277 1278 var pend sync.WaitGroup 1279 pend.Add(len(chain)) 1280 1281 for i := range chain { 1282 go func(block *types.Block) { 1283 defer pend.Done() 1284 1285 // try to retrieve a block by its canonical hash and see if the block data can be retrieved. 1286 for { 1287 ch := rawdb.ReadCanonicalHash(blockchain.db, block.NumberU64()) 1288 if ch == (common.Hash{}) { 1289 continue // busy wait for canonical hash to be written 1290 } 1291 if ch != block.Hash() { 1292 t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex()) 1293 } 1294 fb := rawdb.ReadBlock(blockchain.db, ch, block.NumberU64()) 1295 if fb == nil { 1296 t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex()) 1297 } 1298 if fb.Hash() != block.Hash() { 1299 t.Fatalf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex()) 1300 } 1301 return 1302 } 1303 }(chain[i]) 1304 1305 if _, err := blockchain.InsertChain(types.Blocks{chain[i]}); err != nil { 1306 t.Fatalf("failed to insert block %d: %v", i, err) 1307 } 1308 } 1309 pend.Wait() 1310 } 1311 1312 func TestEIP155Transition(t *testing.T) { 1313 // Configure and generate a sample block chain 1314 var ( 1315 db = rawdb.NewMemoryDatabase() 1316 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1317 address = crypto.PubkeyToAddress(key.PublicKey) 1318 funds = big.NewInt(1000000000) 1319 deleteAddr = common.Address{1} 1320 gspec = &Genesis{ 1321 Config: ¶ms.ChainConfig{ChainID: big.NewInt(1), EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}, 1322 Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, 1323 } 1324 genesis = gspec.MustCommit(db) 1325 ) 1326 1327 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1328 defer blockchain.Stop() 1329 1330 blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1331 var ( 1332 tx *types.Transaction 1333 err error 1334 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1335 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1336 } 1337 ) 1338 switch i { 1339 case 0: 1340 tx, err = basicTx(types.HomesteadSigner{}) 1341 if err != nil { 1342 t.Fatal(err) 1343 } 1344 block.AddTx(tx) 1345 case 2: 1346 tx, err = basicTx(types.HomesteadSigner{}) 1347 if err != nil { 1348 t.Fatal(err) 1349 } 1350 block.AddTx(tx) 1351 1352 tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainID)) 1353 if err != nil { 1354 t.Fatal(err) 1355 } 1356 block.AddTx(tx) 1357 case 3: 1358 tx, err = basicTx(types.HomesteadSigner{}) 1359 if err != nil { 1360 t.Fatal(err) 1361 } 1362 block.AddTx(tx) 1363 1364 tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainID)) 1365 if err != nil { 1366 t.Fatal(err) 1367 } 1368 block.AddTx(tx) 1369 } 1370 }) 1371 1372 if _, err := blockchain.InsertChain(blocks); err != nil { 1373 t.Fatal(err) 1374 } 1375 block := blockchain.GetBlockByNumber(1) 1376 if block.Transactions()[0].Protected() { 1377 t.Error("Expected block[0].txs[0] to not be replay protected") 1378 } 1379 1380 block = blockchain.GetBlockByNumber(3) 1381 if block.Transactions()[0].Protected() { 1382 t.Error("Expected block[3].txs[0] to not be replay protected") 1383 } 1384 if !block.Transactions()[1].Protected() { 1385 t.Error("Expected block[3].txs[1] to be replay protected") 1386 } 1387 if _, err := blockchain.InsertChain(blocks[4:]); err != nil { 1388 t.Fatal(err) 1389 } 1390 1391 // generate an invalid chain id transaction 1392 config := ¶ms.ChainConfig{ChainID: big.NewInt(2), EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)} 1393 blocks, _ = GenerateChain(config, blocks[len(blocks)-1], ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1394 var ( 1395 tx *types.Transaction 1396 err error 1397 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1398 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1399 } 1400 ) 1401 if i == 0 { 1402 tx, err = basicTx(types.NewEIP155Signer(big.NewInt(2))) 1403 if err != nil { 1404 t.Fatal(err) 1405 } 1406 block.AddTx(tx) 1407 } 1408 }) 1409 _, err := blockchain.InsertChain(blocks) 1410 if err != types.ErrInvalidChainId { 1411 t.Error("expected error:", types.ErrInvalidChainId) 1412 } 1413 } 1414 1415 func TestEIP161AccountRemoval(t *testing.T) { 1416 // Configure and generate a sample block chain 1417 var ( 1418 db = rawdb.NewMemoryDatabase() 1419 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1420 address = crypto.PubkeyToAddress(key.PublicKey) 1421 funds = big.NewInt(1000000000) 1422 theAddr = common.Address{1} 1423 gspec = &Genesis{ 1424 Config: ¶ms.ChainConfig{ 1425 ChainID: big.NewInt(1), 1426 HomesteadBlock: new(big.Int), 1427 EIP155Block: new(big.Int), 1428 EIP150Block: new(big.Int), 1429 EIP158Block: big.NewInt(2), 1430 }, 1431 Alloc: GenesisAlloc{address: {Balance: funds}}, 1432 } 1433 genesis = gspec.MustCommit(db) 1434 ) 1435 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1436 defer blockchain.Stop() 1437 1438 blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, block *BlockGen) { 1439 var ( 1440 tx *types.Transaction 1441 err error 1442 signer = types.NewEIP155Signer(gspec.Config.ChainID) 1443 ) 1444 switch i { 1445 case 0: 1446 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1447 case 1: 1448 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1449 case 2: 1450 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1451 } 1452 if err != nil { 1453 t.Fatal(err) 1454 } 1455 block.AddTx(tx) 1456 }) 1457 // account must exist pre eip 161 1458 if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { 1459 t.Fatal(err) 1460 } 1461 if st, _ := blockchain.State(); !st.Exist(theAddr) { 1462 t.Error("expected account to exist") 1463 } 1464 1465 // account needs to be deleted post eip 161 1466 if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil { 1467 t.Fatal(err) 1468 } 1469 if st, _ := blockchain.State(); st.Exist(theAddr) { 1470 t.Error("account should not exist") 1471 } 1472 1473 // account musn't be created post eip 161 1474 if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil { 1475 t.Fatal(err) 1476 } 1477 if st, _ := blockchain.State(); st.Exist(theAddr) { 1478 t.Error("account should not exist") 1479 } 1480 } 1481 1482 // This is a regression test (i.e. as weird as it is, don't delete it ever), which 1483 // tests that under weird reorg conditions the blockchain and its internal header- 1484 // chain return the same latest block/header. 1485 // 1486 // https://github.com/ethereum/go-ethereum/pull/15941 1487 func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { 1488 // Generate a canonical chain to act as the main dataset 1489 engine := ethash.NewFaker() 1490 1491 db := rawdb.NewMemoryDatabase() 1492 genesis := new(Genesis).MustCommit(db) 1493 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1494 1495 // Generate a bunch of fork blocks, each side forking from the canonical chain 1496 forks := make([]*types.Block, len(blocks)) 1497 for i := 0; i < len(forks); i++ { 1498 parent := genesis 1499 if i > 0 { 1500 parent = blocks[i-1] 1501 } 1502 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1503 forks[i] = fork[0] 1504 } 1505 // Import the canonical and fork chain side by side, verifying the current block 1506 // and current header consistency 1507 diskdb := rawdb.NewMemoryDatabase() 1508 new(Genesis).MustCommit(diskdb) 1509 1510 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1511 if err != nil { 1512 t.Fatalf("failed to create tester chain: %v", err) 1513 } 1514 for i := 0; i < len(blocks); i++ { 1515 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1516 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1517 } 1518 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1519 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]) 1520 } 1521 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1522 t.Fatalf(" fork %d: failed to insert into chain: %v", i, err) 1523 } 1524 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1525 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]) 1526 } 1527 } 1528 } 1529 1530 // Tests that importing small side forks doesn't leave junk in the trie database 1531 // cache (which would eventually cause memory issues). 1532 func TestTrieForkGC(t *testing.T) { 1533 // Generate a canonical chain to act as the main dataset 1534 engine := ethash.NewFaker() 1535 1536 db := rawdb.NewMemoryDatabase() 1537 genesis := new(Genesis).MustCommit(db) 1538 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1539 1540 // Generate a bunch of fork blocks, each side forking from the canonical chain 1541 forks := make([]*types.Block, len(blocks)) 1542 for i := 0; i < len(forks); i++ { 1543 parent := genesis 1544 if i > 0 { 1545 parent = blocks[i-1] 1546 } 1547 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1548 forks[i] = fork[0] 1549 } 1550 // Import the canonical and fork chain side by side, forcing the trie cache to cache both 1551 diskdb := rawdb.NewMemoryDatabase() 1552 new(Genesis).MustCommit(diskdb) 1553 1554 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1555 if err != nil { 1556 t.Fatalf("failed to create tester chain: %v", err) 1557 } 1558 for i := 0; i < len(blocks); i++ { 1559 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1560 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1561 } 1562 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1563 t.Fatalf("fork %d: failed to insert into chain: %v", i, err) 1564 } 1565 } 1566 // Dereference all the recent tries and ensure no past trie is left in 1567 for i := 0; i < TriesInMemory; i++ { 1568 chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root()) 1569 chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root()) 1570 } 1571 if len(chain.stateCache.TrieDB().Nodes()) > 0 { 1572 t.Fatalf("stale tries still alive after garbase collection") 1573 } 1574 } 1575 1576 // Tests that doing large reorgs works even if the state associated with the 1577 // forking point is not available any more. 1578 func TestLargeReorgTrieGC(t *testing.T) { 1579 // Generate the original common chain segment and the two competing forks 1580 engine := ethash.NewFaker() 1581 1582 db := rawdb.NewMemoryDatabase() 1583 genesis := new(Genesis).MustCommit(db) 1584 1585 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1586 original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1587 competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*TriesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) 1588 1589 // Import the shared chain and the original canonical one 1590 diskdb := rawdb.NewMemoryDatabase() 1591 new(Genesis).MustCommit(diskdb) 1592 1593 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1594 if err != nil { 1595 t.Fatalf("failed to create tester chain: %v", err) 1596 } 1597 if _, err := chain.InsertChain(shared); err != nil { 1598 t.Fatalf("failed to insert shared chain: %v", err) 1599 } 1600 if _, err := chain.InsertChain(original); err != nil { 1601 t.Fatalf("failed to insert original chain: %v", err) 1602 } 1603 // Ensure that the state associated with the forking point is pruned away 1604 if node, _ := chain.stateCache.TrieDB().Node(shared[len(shared)-1].Root()); node != nil { 1605 t.Fatalf("common-but-old ancestor still cache") 1606 } 1607 // Import the competitor chain without exceeding the canonical's TD and ensure 1608 // we have not processed any of the blocks (protection against malicious blocks) 1609 if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil { 1610 t.Fatalf("failed to insert competitor chain: %v", err) 1611 } 1612 for i, block := range competitor[:len(competitor)-2] { 1613 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1614 t.Fatalf("competitor %d: low TD chain became processed", i) 1615 } 1616 } 1617 // Import the head of the competitor chain, triggering the reorg and ensure we 1618 // successfully reprocess all the stashed away blocks. 1619 if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil { 1620 t.Fatalf("failed to finalize competitor chain: %v", err) 1621 } 1622 for i, block := range competitor[:len(competitor)-TriesInMemory] { 1623 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1624 t.Fatalf("competitor %d: competing chain state missing", i) 1625 } 1626 } 1627 } 1628 1629 func TestBlockchainRecovery(t *testing.T) { 1630 // Configure and generate a sample block chain 1631 var ( 1632 gendb = rawdb.NewMemoryDatabase() 1633 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1634 address = crypto.PubkeyToAddress(key.PublicKey) 1635 funds = big.NewInt(1000000000) 1636 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 1637 genesis = gspec.MustCommit(gendb) 1638 ) 1639 height := uint64(1024) 1640 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil) 1641 1642 // Import the chain as a ancient-first node and ensure all pointers are updated 1643 frdir, err := ioutil.TempDir("", "") 1644 if err != nil { 1645 t.Fatalf("failed to create temp freezer dir: %v", err) 1646 } 1647 defer os.Remove(frdir) 1648 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "") 1649 if err != nil { 1650 t.Fatalf("failed to create temp freezer db: %v", err) 1651 } 1652 gspec.MustCommit(ancientDb) 1653 ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1654 1655 headers := make([]*types.Header, len(blocks)) 1656 for i, block := range blocks { 1657 headers[i] = block.Header() 1658 } 1659 if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { 1660 t.Fatalf("failed to insert header %d: %v", n, err) 1661 } 1662 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { 1663 t.Fatalf("failed to insert receipt %d: %v", n, err) 1664 } 1665 ancient.Stop() 1666 1667 // Destroy head fast block manually 1668 midBlock := blocks[len(blocks)/2] 1669 rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash()) 1670 1671 // Reopen broken blockchain again 1672 ancient, _ = NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1673 defer ancient.Stop() 1674 if num := ancient.CurrentBlock().NumberU64(); num != 0 { 1675 t.Errorf("head block mismatch: have #%v, want #%v", num, 0) 1676 } 1677 if num := ancient.CurrentFastBlock().NumberU64(); num != midBlock.NumberU64() { 1678 t.Errorf("head fast-block mismatch: have #%v, want #%v", num, midBlock.NumberU64()) 1679 } 1680 if num := ancient.CurrentHeader().Number.Uint64(); num != midBlock.NumberU64() { 1681 t.Errorf("head header mismatch: have #%v, want #%v", num, midBlock.NumberU64()) 1682 } 1683 } 1684 1685 func TestIncompleteAncientReceiptChainInsertion(t *testing.T) { 1686 // Configure and generate a sample block chain 1687 var ( 1688 gendb = rawdb.NewMemoryDatabase() 1689 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1690 address = crypto.PubkeyToAddress(key.PublicKey) 1691 funds = big.NewInt(1000000000) 1692 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 1693 genesis = gspec.MustCommit(gendb) 1694 ) 1695 height := uint64(1024) 1696 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil) 1697 1698 // Import the chain as a ancient-first node and ensure all pointers are updated 1699 frdir, err := ioutil.TempDir("", "") 1700 if err != nil { 1701 t.Fatalf("failed to create temp freezer dir: %v", err) 1702 } 1703 defer os.Remove(frdir) 1704 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "") 1705 if err != nil { 1706 t.Fatalf("failed to create temp freezer db: %v", err) 1707 } 1708 gspec.MustCommit(ancientDb) 1709 ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1710 defer ancient.Stop() 1711 1712 headers := make([]*types.Header, len(blocks)) 1713 for i, block := range blocks { 1714 headers[i] = block.Header() 1715 } 1716 if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { 1717 t.Fatalf("failed to insert header %d: %v", n, err) 1718 } 1719 // Abort ancient receipt chain insertion deliberately 1720 ancient.terminateInsert = func(hash common.Hash, number uint64) bool { 1721 return number == blocks[len(blocks)/2].NumberU64() 1722 } 1723 previousFastBlock := ancient.CurrentFastBlock() 1724 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err == nil { 1725 t.Fatalf("failed to insert receipt %d: %v", n, err) 1726 } 1727 if ancient.CurrentFastBlock().NumberU64() != previousFastBlock.NumberU64() { 1728 t.Fatalf("failed to rollback ancient data, want %d, have %d", previousFastBlock.NumberU64(), ancient.CurrentFastBlock().NumberU64()) 1729 } 1730 if frozen, err := ancient.db.Ancients(); err != nil || frozen != 1 { 1731 t.Fatalf("failed to truncate ancient data") 1732 } 1733 ancient.terminateInsert = nil 1734 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { 1735 t.Fatalf("failed to insert receipt %d: %v", n, err) 1736 } 1737 if ancient.CurrentFastBlock().NumberU64() != blocks[len(blocks)-1].NumberU64() { 1738 t.Fatalf("failed to insert ancient recept chain after rollback") 1739 } 1740 } 1741 1742 // Tests that importing a very large side fork, which is larger than the canon chain, 1743 // but where the difficulty per block is kept low: this means that it will not 1744 // overtake the 'canon' chain until after it's passed canon by about 200 blocks. 1745 // 1746 // Details at: 1747 // - https://github.com/ethereum/go-ethereum/issues/18977 1748 // - https://github.com/ethereum/go-ethereum/pull/18988 1749 func TestLowDiffLongChain(t *testing.T) { 1750 // Generate a canonical chain to act as the main dataset 1751 engine := ethash.NewFaker() 1752 db := rawdb.NewMemoryDatabase() 1753 genesis := new(Genesis).MustCommit(db) 1754 1755 // We must use a pretty long chain to ensure that the fork doesn't overtake us 1756 // until after at least 128 blocks post tip 1757 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 6*TriesInMemory, func(i int, b *BlockGen) { 1758 b.SetCoinbase(common.Address{1}) 1759 b.OffsetTime(-9) 1760 }) 1761 1762 // Import the canonical chain 1763 diskdb := rawdb.NewMemoryDatabase() 1764 new(Genesis).MustCommit(diskdb) 1765 1766 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1767 if err != nil { 1768 t.Fatalf("failed to create tester chain: %v", err) 1769 } 1770 if n, err := chain.InsertChain(blocks); err != nil { 1771 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 1772 } 1773 // Generate fork chain, starting from an early block 1774 parent := blocks[10] 1775 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 8*TriesInMemory, func(i int, b *BlockGen) { 1776 b.SetCoinbase(common.Address{2}) 1777 }) 1778 1779 // And now import the fork 1780 if i, err := chain.InsertChain(fork); err != nil { 1781 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1782 } 1783 head := chain.CurrentBlock() 1784 if got := fork[len(fork)-1].Hash(); got != head.Hash() { 1785 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 1786 } 1787 // Sanity check that all the canonical numbers are present 1788 header := chain.CurrentHeader() 1789 for number := head.NumberU64(); number > 0; number-- { 1790 if hash := chain.GetHeaderByNumber(number).Hash(); hash != header.Hash() { 1791 t.Fatalf("header %d: canonical hash mismatch: have %x, want %x", number, hash, header.Hash()) 1792 } 1793 header = chain.GetHeader(header.ParentHash, number-1) 1794 } 1795 } 1796 1797 // Tests that importing a sidechain (S), where 1798 // - S is sidechain, containing blocks [Sn...Sm] 1799 // - C is canon chain, containing blocks [G..Cn..Cm] 1800 // - A common ancestor is placed at prune-point + blocksBetweenCommonAncestorAndPruneblock 1801 // - The sidechain S is prepended with numCanonBlocksInSidechain blocks from the canon chain 1802 func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommonAncestorAndPruneblock int) { 1803 1804 // Generate a canonical chain to act as the main dataset 1805 engine := ethash.NewFaker() 1806 db := rawdb.NewMemoryDatabase() 1807 genesis := new(Genesis).MustCommit(db) 1808 1809 // Generate and import the canonical chain 1810 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, nil) 1811 diskdb := rawdb.NewMemoryDatabase() 1812 new(Genesis).MustCommit(diskdb) 1813 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1814 if err != nil { 1815 t.Fatalf("failed to create tester chain: %v", err) 1816 } 1817 if n, err := chain.InsertChain(blocks); err != nil { 1818 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 1819 } 1820 1821 lastPrunedIndex := len(blocks) - TriesInMemory - 1 1822 lastPrunedBlock := blocks[lastPrunedIndex] 1823 firstNonPrunedBlock := blocks[len(blocks)-TriesInMemory] 1824 1825 // Verify pruning of lastPrunedBlock 1826 if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) { 1827 t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64()) 1828 } 1829 // Verify firstNonPrunedBlock is not pruned 1830 if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) { 1831 t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64()) 1832 } 1833 // Generate the sidechain 1834 // First block should be a known block, block after should be a pruned block. So 1835 // canon(pruned), side, side... 1836 1837 // Generate fork chain, make it longer than canon 1838 parentIndex := lastPrunedIndex + blocksBetweenCommonAncestorAndPruneblock 1839 parent := blocks[parentIndex] 1840 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { 1841 b.SetCoinbase(common.Address{2}) 1842 }) 1843 // Prepend the parent(s) 1844 var sidechain []*types.Block 1845 for i := numCanonBlocksInSidechain; i > 0; i-- { 1846 sidechain = append(sidechain, blocks[parentIndex+1-i]) 1847 } 1848 sidechain = append(sidechain, fork...) 1849 _, err = chain.InsertChain(sidechain) 1850 if err != nil { 1851 t.Errorf("Got error, %v", err) 1852 } 1853 head := chain.CurrentBlock() 1854 if got := fork[len(fork)-1].Hash(); got != head.Hash() { 1855 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 1856 } 1857 } 1858 1859 // Tests that importing a sidechain (S), where 1860 // - S is sidechain, containing blocks [Sn...Sm] 1861 // - C is canon chain, containing blocks [G..Cn..Cm] 1862 // - The common ancestor Cc is pruned 1863 // - The first block in S: Sn, is == Cn 1864 // That is: the sidechain for import contains some blocks already present in canon chain. 1865 // So the blocks are 1866 // [ Cn, Cn+1, Cc, Sn+3 ... Sm] 1867 // ^ ^ ^ pruned 1868 func TestPrunedImportSide(t *testing.T) { 1869 //glogger := log.NewGlogHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false))) 1870 //glogger.Verbosity(3) 1871 //log.Root().SetHandler(log.Handler(glogger)) 1872 testSideImport(t, 3, 3) 1873 testSideImport(t, 3, -3) 1874 testSideImport(t, 10, 0) 1875 testSideImport(t, 1, 10) 1876 testSideImport(t, 1, -10) 1877 } 1878 1879 func TestInsertKnownHeaders(t *testing.T) { testInsertKnownChainData(t, "headers") } 1880 func TestInsertKnownReceiptChain(t *testing.T) { testInsertKnownChainData(t, "receipts") } 1881 func TestInsertKnownBlocks(t *testing.T) { testInsertKnownChainData(t, "blocks") } 1882 1883 func testInsertKnownChainData(t *testing.T, typ string) { 1884 engine := ethash.NewFaker() 1885 1886 db := rawdb.NewMemoryDatabase() 1887 genesis := new(Genesis).MustCommit(db) 1888 1889 blocks, receipts := GenerateChain(params.TestChainConfig, genesis, engine, db, 32, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1890 // A longer chain but total difficulty is lower. 1891 blocks2, receipts2 := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], engine, db, 65, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1892 // A shorter chain but total difficulty is higher. 1893 blocks3, receipts3 := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], engine, db, 64, func(i int, b *BlockGen) { 1894 b.SetCoinbase(common.Address{1}) 1895 b.OffsetTime(-9) // A higher difficulty 1896 }) 1897 // Import the shared chain and the original canonical one 1898 dir, err := ioutil.TempDir("", "") 1899 if err != nil { 1900 t.Fatalf("failed to create temp freezer dir: %v", err) 1901 } 1902 defer os.Remove(dir) 1903 chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), dir, "") 1904 if err != nil { 1905 t.Fatalf("failed to create temp freezer db: %v", err) 1906 } 1907 new(Genesis).MustCommit(chaindb) 1908 defer os.RemoveAll(dir) 1909 1910 chain, err := NewBlockChain(chaindb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1911 if err != nil { 1912 t.Fatalf("failed to create tester chain: %v", err) 1913 } 1914 1915 var ( 1916 inserter func(blocks []*types.Block, receipts []types.Receipts) error 1917 asserter func(t *testing.T, block *types.Block) 1918 ) 1919 headers, headers2 := make([]*types.Header, 0, len(blocks)), make([]*types.Header, 0, len(blocks2)) 1920 for _, block := range blocks { 1921 headers = append(headers, block.Header()) 1922 } 1923 for _, block := range blocks2 { 1924 headers2 = append(headers2, block.Header()) 1925 } 1926 if typ == "headers" { 1927 inserter = func(blocks []*types.Block, receipts []types.Receipts) error { 1928 headers := make([]*types.Header, 0, len(blocks)) 1929 for _, block := range blocks { 1930 headers = append(headers, block.Header()) 1931 } 1932 _, err := chain.InsertHeaderChain(headers, 1) 1933 return err 1934 } 1935 asserter = func(t *testing.T, block *types.Block) { 1936 if chain.CurrentHeader().Hash() != block.Hash() { 1937 t.Fatalf("current head header mismatch, have %v, want %v", chain.CurrentHeader().Hash().Hex(), block.Hash().Hex()) 1938 } 1939 } 1940 } else if typ == "receipts" { 1941 inserter = func(blocks []*types.Block, receipts []types.Receipts) error { 1942 headers := make([]*types.Header, 0, len(blocks)) 1943 for _, block := range blocks { 1944 headers = append(headers, block.Header()) 1945 } 1946 _, err := chain.InsertHeaderChain(headers, 1) 1947 if err != nil { 1948 return err 1949 } 1950 _, err = chain.InsertReceiptChain(blocks, receipts, 0) 1951 return err 1952 } 1953 asserter = func(t *testing.T, block *types.Block) { 1954 if chain.CurrentFastBlock().Hash() != block.Hash() { 1955 t.Fatalf("current head fast block mismatch, have %v, want %v", chain.CurrentFastBlock().Hash().Hex(), block.Hash().Hex()) 1956 } 1957 } 1958 } else { 1959 inserter = func(blocks []*types.Block, receipts []types.Receipts) error { 1960 _, err := chain.InsertChain(blocks) 1961 return err 1962 } 1963 asserter = func(t *testing.T, block *types.Block) { 1964 if chain.CurrentBlock().Hash() != block.Hash() { 1965 t.Fatalf("current head block mismatch, have %v, want %v", chain.CurrentBlock().Hash().Hex(), block.Hash().Hex()) 1966 } 1967 } 1968 } 1969 1970 if err := inserter(blocks, receipts); err != nil { 1971 t.Fatalf("failed to insert chain data: %v", err) 1972 } 1973 1974 // Reimport the chain data again. All the imported 1975 // chain data are regarded "known" data. 1976 if err := inserter(blocks, receipts); err != nil { 1977 t.Fatalf("failed to insert chain data: %v", err) 1978 } 1979 asserter(t, blocks[len(blocks)-1]) 1980 1981 // Import a long canonical chain with some known data as prefix. 1982 var rollback []common.Hash 1983 for i := len(blocks) / 2; i < len(blocks); i++ { 1984 rollback = append(rollback, blocks[i].Hash()) 1985 } 1986 chain.Rollback(rollback) 1987 if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { 1988 t.Fatalf("failed to insert chain data: %v", err) 1989 } 1990 asserter(t, blocks2[len(blocks2)-1]) 1991 1992 // Import a heavier shorter but higher total difficulty chain with some known data as prefix. 1993 if err := inserter(append(blocks, blocks3...), append(receipts, receipts3...)); err != nil { 1994 t.Fatalf("failed to insert chain data: %v", err) 1995 } 1996 asserter(t, blocks3[len(blocks3)-1]) 1997 1998 // Import a longer but lower total difficulty chain with some known data as prefix. 1999 if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { 2000 t.Fatalf("failed to insert chain data: %v", err) 2001 } 2002 // The head shouldn't change. 2003 asserter(t, blocks3[len(blocks3)-1]) 2004 2005 // Rollback the heavier chain and re-insert the longer chain again 2006 for i := 0; i < len(blocks3); i++ { 2007 rollback = append(rollback, blocks3[i].Hash()) 2008 } 2009 chain.Rollback(rollback) 2010 2011 if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { 2012 t.Fatalf("failed to insert chain data: %v", err) 2013 } 2014 asserter(t, blocks2[len(blocks2)-1]) 2015 } 2016 2017 // getLongAndShortChains returns two chains, 2018 // A is longer, B is heavier 2019 func getLongAndShortChains() (*BlockChain, []*types.Block, []*types.Block, error) { 2020 // Generate a canonical chain to act as the main dataset 2021 engine := ethash.NewFaker() 2022 db := rawdb.NewMemoryDatabase() 2023 genesis := new(Genesis).MustCommit(db) 2024 2025 // Generate and import the canonical chain, 2026 // Offset the time, to keep the difficulty low 2027 longChain, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 80, func(i int, b *BlockGen) { 2028 b.SetCoinbase(common.Address{1}) 2029 }) 2030 diskdb := rawdb.NewMemoryDatabase() 2031 new(Genesis).MustCommit(diskdb) 2032 2033 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 2034 if err != nil { 2035 return nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err) 2036 } 2037 2038 // Generate fork chain, make it shorter than canon, with common ancestor pretty early 2039 parentIndex := 3 2040 parent := longChain[parentIndex] 2041 heavyChain, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 75, func(i int, b *BlockGen) { 2042 b.SetCoinbase(common.Address{2}) 2043 b.OffsetTime(-9) 2044 }) 2045 // Verify that the test is sane 2046 var ( 2047 longerTd = new(big.Int) 2048 shorterTd = new(big.Int) 2049 ) 2050 for index, b := range longChain { 2051 longerTd.Add(longerTd, b.Difficulty()) 2052 if index <= parentIndex { 2053 shorterTd.Add(shorterTd, b.Difficulty()) 2054 } 2055 } 2056 for _, b := range heavyChain { 2057 shorterTd.Add(shorterTd, b.Difficulty()) 2058 } 2059 if shorterTd.Cmp(longerTd) <= 0 { 2060 return nil, nil, nil, fmt.Errorf("Test is moot, heavyChain td (%v) must be larger than canon td (%v)", shorterTd, longerTd) 2061 } 2062 longerNum := longChain[len(longChain)-1].NumberU64() 2063 shorterNum := heavyChain[len(heavyChain)-1].NumberU64() 2064 if shorterNum >= longerNum { 2065 return nil, nil, nil, fmt.Errorf("Test is moot, heavyChain num (%v) must be lower than canon num (%v)", shorterNum, longerNum) 2066 } 2067 return chain, longChain, heavyChain, nil 2068 } 2069 2070 // TestReorgToShorterRemovesCanonMapping tests that if we 2071 // 1. Have a chain [0 ... N .. X] 2072 // 2. Reorg to shorter but heavier chain [0 ... N ... Y] 2073 // 3. Then there should be no canon mapping for the block at height X 2074 func TestReorgToShorterRemovesCanonMapping(t *testing.T) { 2075 chain, canonblocks, sideblocks, err := getLongAndShortChains() 2076 if err != nil { 2077 t.Fatal(err) 2078 } 2079 if n, err := chain.InsertChain(canonblocks); err != nil { 2080 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2081 } 2082 canonNum := chain.CurrentBlock().NumberU64() 2083 _, err = chain.InsertChain(sideblocks) 2084 if err != nil { 2085 t.Errorf("Got error, %v", err) 2086 } 2087 head := chain.CurrentBlock() 2088 if got := sideblocks[len(sideblocks)-1].Hash(); got != head.Hash() { 2089 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 2090 } 2091 // We have now inserted a sidechain. 2092 if blockByNum := chain.GetBlockByNumber(canonNum); blockByNum != nil { 2093 t.Errorf("expected block to be gone: %v", blockByNum.NumberU64()) 2094 } 2095 if headerByNum := chain.GetHeaderByNumber(canonNum); headerByNum != nil { 2096 t.Errorf("expected header to be gone: %v", headerByNum.Number.Uint64()) 2097 } 2098 } 2099 2100 // TestReorgToShorterRemovesCanonMappingHeaderChain is the same scenario 2101 // as TestReorgToShorterRemovesCanonMapping, but applied on headerchain 2102 // imports -- that is, for fast sync 2103 func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) { 2104 chain, canonblocks, sideblocks, err := getLongAndShortChains() 2105 if err != nil { 2106 t.Fatal(err) 2107 } 2108 // Convert into headers 2109 canonHeaders := make([]*types.Header, len(canonblocks)) 2110 for i, block := range canonblocks { 2111 canonHeaders[i] = block.Header() 2112 } 2113 if n, err := chain.InsertHeaderChain(canonHeaders, 0); err != nil { 2114 t.Fatalf("header %d: failed to insert into chain: %v", n, err) 2115 } 2116 canonNum := chain.CurrentHeader().Number.Uint64() 2117 sideHeaders := make([]*types.Header, len(sideblocks)) 2118 for i, block := range sideblocks { 2119 sideHeaders[i] = block.Header() 2120 } 2121 if n, err := chain.InsertHeaderChain(sideHeaders, 0); err != nil { 2122 t.Fatalf("header %d: failed to insert into chain: %v", n, err) 2123 } 2124 head := chain.CurrentHeader() 2125 if got := sideblocks[len(sideblocks)-1].Hash(); got != head.Hash() { 2126 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 2127 } 2128 // We have now inserted a sidechain. 2129 if blockByNum := chain.GetBlockByNumber(canonNum); blockByNum != nil { 2130 t.Errorf("expected block to be gone: %v", blockByNum.NumberU64()) 2131 } 2132 if headerByNum := chain.GetHeaderByNumber(canonNum); headerByNum != nil { 2133 t.Errorf("expected header to be gone: %v", headerByNum.Number.Uint64()) 2134 } 2135 } 2136 2137 // Benchmarks large blocks with value transfers to non-existing accounts 2138 func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) { 2139 var ( 2140 signer = types.HomesteadSigner{} 2141 testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 2142 testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) 2143 bankFunds = big.NewInt(100000000000000000) 2144 gspec = Genesis{ 2145 Config: params.TestChainConfig, 2146 Alloc: GenesisAlloc{ 2147 testBankAddress: {Balance: bankFunds}, 2148 common.HexToAddress("0xc0de"): { 2149 Code: []byte{0x60, 0x01, 0x50}, 2150 Balance: big.NewInt(0), 2151 }, // push 1, pop 2152 }, 2153 GasLimit: 100e6, // 100 M 2154 } 2155 ) 2156 // Generate the original common chain segment and the two competing forks 2157 engine := ethash.NewFaker() 2158 db := rawdb.NewMemoryDatabase() 2159 genesis := gspec.MustCommit(db) 2160 2161 blockGenerator := func(i int, block *BlockGen) { 2162 block.SetCoinbase(common.Address{1}) 2163 for txi := 0; txi < numTxs; txi++ { 2164 uniq := uint64(i*numTxs + txi) 2165 recipient := recipientFn(uniq) 2166 tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxGas, big.NewInt(1), nil), signer, testBankKey) 2167 if err != nil { 2168 b.Error(err) 2169 } 2170 block.AddTx(tx) 2171 } 2172 } 2173 2174 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, numBlocks, blockGenerator) 2175 b.StopTimer() 2176 b.ResetTimer() 2177 for i := 0; i < b.N; i++ { 2178 // Import the shared chain and the original canonical one 2179 diskdb := rawdb.NewMemoryDatabase() 2180 gspec.MustCommit(diskdb) 2181 2182 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 2183 if err != nil { 2184 b.Fatalf("failed to create tester chain: %v", err) 2185 } 2186 b.StartTimer() 2187 if _, err := chain.InsertChain(shared); err != nil { 2188 b.Fatalf("failed to insert shared chain: %v", err) 2189 } 2190 b.StopTimer() 2191 if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks { 2192 b.Fatalf("Transactions were not included, expected %d, got %d", numTxs*numBlocks, got) 2193 2194 } 2195 } 2196 } 2197 2198 func BenchmarkBlockChain_1x1000ValueTransferToNonexisting(b *testing.B) { 2199 var ( 2200 numTxs = 1000 2201 numBlocks = 1 2202 ) 2203 recipientFn := func(nonce uint64) common.Address { 2204 return common.BigToAddress(big.NewInt(0).SetUint64(1337 + nonce)) 2205 } 2206 dataFn := func(nonce uint64) []byte { 2207 return nil 2208 } 2209 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 2210 } 2211 2212 func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) { 2213 var ( 2214 numTxs = 1000 2215 numBlocks = 1 2216 ) 2217 b.StopTimer() 2218 b.ResetTimer() 2219 2220 recipientFn := func(nonce uint64) common.Address { 2221 return common.BigToAddress(big.NewInt(0).SetUint64(1337)) 2222 } 2223 dataFn := func(nonce uint64) []byte { 2224 return nil 2225 } 2226 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 2227 } 2228 2229 func BenchmarkBlockChain_1x1000Executions(b *testing.B) { 2230 var ( 2231 numTxs = 1000 2232 numBlocks = 1 2233 ) 2234 b.StopTimer() 2235 b.ResetTimer() 2236 2237 recipientFn := func(nonce uint64) common.Address { 2238 return common.BigToAddress(big.NewInt(0).SetUint64(0xc0de)) 2239 } 2240 dataFn := func(nonce uint64) []byte { 2241 return nil 2242 } 2243 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 2244 } 2245 2246 // Tests that importing a some old blocks, where all blocks are before the 2247 // pruning point. 2248 // This internally leads to a sidechain import, since the blocks trigger an 2249 // ErrPrunedAncestor error. 2250 // This may e.g. happen if 2251 // 1. Downloader rollbacks a batch of inserted blocks and exits 2252 // 2. Downloader starts to sync again 2253 // 3. The blocks fetched are all known and canonical blocks 2254 func TestSideImportPrunedBlocks(t *testing.T) { 2255 // Generate a canonical chain to act as the main dataset 2256 engine := ethash.NewFaker() 2257 db := rawdb.NewMemoryDatabase() 2258 genesis := new(Genesis).MustCommit(db) 2259 2260 // Generate and import the canonical chain 2261 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, nil) 2262 diskdb := rawdb.NewMemoryDatabase() 2263 new(Genesis).MustCommit(diskdb) 2264 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 2265 if err != nil { 2266 t.Fatalf("failed to create tester chain: %v", err) 2267 } 2268 if n, err := chain.InsertChain(blocks); err != nil { 2269 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2270 } 2271 2272 lastPrunedIndex := len(blocks) - TriesInMemory - 1 2273 lastPrunedBlock := blocks[lastPrunedIndex] 2274 2275 // Verify pruning of lastPrunedBlock 2276 if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) { 2277 t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64()) 2278 } 2279 firstNonPrunedBlock := blocks[len(blocks)-TriesInMemory] 2280 // Verify firstNonPrunedBlock is not pruned 2281 if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) { 2282 t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64()) 2283 } 2284 // Now re-import some old blocks 2285 blockToReimport := blocks[5:8] 2286 _, err = chain.InsertChain(blockToReimport) 2287 if err != nil { 2288 t.Errorf("Got error, %v", err) 2289 } 2290 } 2291 2292 // TestDeleteCreateRevert tests a weird state transition corner case that we hit 2293 // while changing the internals of statedb. The workflow is that a contract is 2294 // self destructed, then in a followup transaction (but same block) it's created 2295 // again and the transaction reverted. 2296 // 2297 // The original statedb implementation flushed dirty objects to the tries after 2298 // each transaction, so this works ok. The rework accumulated writes in memory 2299 // first, but the journal wiped the entire state object on create-revert. 2300 func TestDeleteCreateRevert(t *testing.T) { 2301 var ( 2302 aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") 2303 bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb") 2304 // Generate a canonical chain to act as the main dataset 2305 engine = ethash.NewFaker() 2306 db = rawdb.NewMemoryDatabase() 2307 2308 // A sender who makes transactions, has some funds 2309 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 2310 address = crypto.PubkeyToAddress(key.PublicKey) 2311 funds = big.NewInt(1000000000) 2312 gspec = &Genesis{ 2313 Config: params.TestChainConfig, 2314 Alloc: GenesisAlloc{ 2315 address: {Balance: funds}, 2316 // The address 0xAAAAA selfdestructs if called 2317 aa: { 2318 // Code needs to just selfdestruct 2319 Code: []byte{byte(vm.PC), 0xFF}, 2320 Nonce: 1, 2321 Balance: big.NewInt(0), 2322 }, 2323 // The address 0xBBBB send 1 wei to 0xAAAA, then reverts 2324 bb: { 2325 Code: []byte{ 2326 byte(vm.PC), // [0] 2327 byte(vm.DUP1), // [0,0] 2328 byte(vm.DUP1), // [0,0,0] 2329 byte(vm.DUP1), // [0,0,0,0] 2330 byte(vm.PUSH1), 0x01, // [0,0,0,0,1] (value) 2331 byte(vm.PUSH2), 0xaa, 0xaa, // [0,0,0,0,1, 0xaaaa] 2332 byte(vm.GAS), 2333 byte(vm.CALL), 2334 byte(vm.REVERT), 2335 }, 2336 Balance: big.NewInt(1), 2337 }, 2338 }, 2339 } 2340 genesis = gspec.MustCommit(db) 2341 ) 2342 2343 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 1, func(i int, b *BlockGen) { 2344 b.SetCoinbase(common.Address{1}) 2345 // One transaction to AAAA 2346 tx, _ := types.SignTx(types.NewTransaction(0, aa, 2347 big.NewInt(0), 50000, big.NewInt(1), nil), types.HomesteadSigner{}, key) 2348 b.AddTx(tx) 2349 // One transaction to BBBB 2350 tx, _ = types.SignTx(types.NewTransaction(1, bb, 2351 big.NewInt(0), 100000, big.NewInt(1), nil), types.HomesteadSigner{}, key) 2352 b.AddTx(tx) 2353 }) 2354 // Import the canonical chain 2355 diskdb := rawdb.NewMemoryDatabase() 2356 gspec.MustCommit(diskdb) 2357 2358 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 2359 if err != nil { 2360 t.Fatalf("failed to create tester chain: %v", err) 2361 } 2362 if n, err := chain.InsertChain(blocks); err != nil { 2363 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2364 } 2365 }