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