github.com/ethereum-optimism/optimism/l2geth@v0.0.0-20230612200230-50b04ade19e3/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 "github.com/ethereum-optimism/optimism/l2geth/common" 31 "github.com/ethereum-optimism/optimism/l2geth/consensus" 32 "github.com/ethereum-optimism/optimism/l2geth/consensus/ethash" 33 "github.com/ethereum-optimism/optimism/l2geth/core/rawdb" 34 "github.com/ethereum-optimism/optimism/l2geth/core/state" 35 "github.com/ethereum-optimism/optimism/l2geth/core/types" 36 "github.com/ethereum-optimism/optimism/l2geth/core/vm" 37 "github.com/ethereum-optimism/optimism/l2geth/crypto" 38 "github.com/ethereum-optimism/optimism/l2geth/ethdb" 39 "github.com/ethereum-optimism/optimism/l2geth/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 t.Skip("UsingOVM") 820 var ( 821 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 822 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 823 key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 824 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 825 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 826 addr3 = crypto.PubkeyToAddress(key3.PublicKey) 827 db = rawdb.NewMemoryDatabase() 828 gspec = &Genesis{ 829 Config: params.TestChainConfig, 830 GasLimit: 3141592, 831 Alloc: GenesisAlloc{ 832 addr1: {Balance: big.NewInt(1000000)}, 833 addr2: {Balance: big.NewInt(1000000)}, 834 addr3: {Balance: big.NewInt(1000000)}, 835 }, 836 } 837 genesis = gspec.MustCommit(db) 838 signer = types.NewEIP155Signer(gspec.Config.ChainID) 839 ) 840 841 // Create two transactions shared between the chains: 842 // - postponed: transaction included at a later block in the forked chain 843 // - swapped: transaction included at the same block number in the forked chain 844 postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 845 swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 846 847 // Create two transactions that will be dropped by the forked chain: 848 // - pastDrop: transaction dropped retroactively from a past block 849 // - freshDrop: transaction dropped exactly at the block where the reorg is detected 850 var pastDrop, freshDrop *types.Transaction 851 852 // Create three transactions that will be added in the forked chain: 853 // - pastAdd: transaction added before the reorganization is detected 854 // - freshAdd: transaction added at the exact block the reorg is detected 855 // - futureAdd: transaction added after the reorg has already finished 856 var pastAdd, freshAdd, futureAdd *types.Transaction 857 858 chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) { 859 switch i { 860 case 0: 861 pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 862 863 gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point 864 gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork 865 866 case 2: 867 freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 868 869 gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point 870 gen.AddTx(swapped) // This transaction will be swapped out at the exact height 871 872 gen.OffsetTime(9) // Lower the block difficulty to simulate a weaker chain 873 } 874 }) 875 // Import the chain. This runs all block validation rules. 876 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 877 if i, err := blockchain.InsertChain(chain); err != nil { 878 t.Fatalf("failed to insert original chain[%d]: %v", i, err) 879 } 880 defer blockchain.Stop() 881 882 // overwrite the old chain 883 chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) { 884 switch i { 885 case 0: 886 pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 887 gen.AddTx(pastAdd) // This transaction needs to be injected during reorg 888 889 case 2: 890 gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain 891 gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain 892 893 freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 894 gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time 895 896 case 3: 897 futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 898 gen.AddTx(futureAdd) // This transaction will be added after a full reorg 899 } 900 }) 901 if _, err := blockchain.InsertChain(chain); err != nil { 902 t.Fatalf("failed to insert forked chain: %v", err) 903 } 904 905 // removed tx 906 for i, tx := range (types.Transactions{pastDrop, freshDrop}) { 907 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn != nil { 908 t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) 909 } 910 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt != nil { 911 t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt) 912 } 913 } 914 // added tx 915 for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) { 916 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 917 t.Errorf("add %d: expected tx to be found", i) 918 } 919 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt == nil { 920 t.Errorf("add %d: expected receipt to be found", i) 921 } 922 } 923 // shared tx 924 for i, tx := range (types.Transactions{postponed, swapped}) { 925 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 926 t.Errorf("share %d: expected tx to be found", i) 927 } 928 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt == nil { 929 t.Errorf("share %d: expected receipt to be found", i) 930 } 931 } 932 } 933 934 func TestLogReorgs(t *testing.T) { 935 var ( 936 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 937 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 938 db = rawdb.NewMemoryDatabase() 939 // this code generates a log 940 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 941 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 942 genesis = gspec.MustCommit(db) 943 signer = types.NewEIP155Signer(gspec.Config.ChainID) 944 ) 945 946 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 947 defer blockchain.Stop() 948 949 rmLogsCh := make(chan RemovedLogsEvent) 950 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 951 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 952 if i == 1 { 953 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 954 if err != nil { 955 t.Fatalf("failed to create tx: %v", err) 956 } 957 gen.AddTx(tx) 958 } 959 }) 960 if _, err := blockchain.InsertChain(chain); err != nil { 961 t.Fatalf("failed to insert chain: %v", err) 962 } 963 964 chain, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 965 done := make(chan struct{}) 966 go func() { 967 ev := <-rmLogsCh 968 if len(ev.Logs) == 0 { 969 t.Error("expected logs") 970 } 971 close(done) 972 }() 973 if _, err := blockchain.InsertChain(chain); err != nil { 974 t.Fatalf("failed to insert forked chain: %v", err) 975 } 976 timeout := time.NewTimer(1 * time.Second) 977 select { 978 case <-done: 979 case <-timeout.C: 980 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 981 } 982 } 983 984 func TestLogRebirth(t *testing.T) { 985 var ( 986 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 987 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 988 db = rawdb.NewMemoryDatabase() 989 990 // this code generates a log 991 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 992 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 993 genesis = gspec.MustCommit(db) 994 signer = types.NewEIP155Signer(gspec.Config.ChainID) 995 newLogCh = make(chan bool) 996 removeLogCh = make(chan bool) 997 ) 998 999 // validateLogEvent checks whether the received logs number is equal with expected. 1000 validateLogEvent := func(sink interface{}, result chan bool, expect int) { 1001 chanval := reflect.ValueOf(sink) 1002 chantyp := chanval.Type() 1003 if chantyp.Kind() != reflect.Chan || chantyp.ChanDir()&reflect.RecvDir == 0 { 1004 t.Fatalf("invalid channel, given type %v", chantyp) 1005 } 1006 cnt := 0 1007 var recv []reflect.Value 1008 timeout := time.After(1 * time.Second) 1009 cases := []reflect.SelectCase{{Chan: chanval, Dir: reflect.SelectRecv}, {Chan: reflect.ValueOf(timeout), Dir: reflect.SelectRecv}} 1010 for { 1011 chose, v, _ := reflect.Select(cases) 1012 if chose == 1 { 1013 // Not enough event received 1014 result <- false 1015 return 1016 } 1017 cnt += 1 1018 recv = append(recv, v) 1019 if cnt == expect { 1020 break 1021 } 1022 } 1023 done := time.After(50 * time.Millisecond) 1024 cases = cases[:1] 1025 cases = append(cases, reflect.SelectCase{Chan: reflect.ValueOf(done), Dir: reflect.SelectRecv}) 1026 chose, _, _ := reflect.Select(cases) 1027 // If chose equal 0, it means receiving redundant events. 1028 if chose == 1 { 1029 result <- true 1030 } else { 1031 result <- false 1032 } 1033 } 1034 1035 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1036 defer blockchain.Stop() 1037 1038 logsCh := make(chan []*types.Log) 1039 blockchain.SubscribeLogsEvent(logsCh) 1040 1041 rmLogsCh := make(chan RemovedLogsEvent) 1042 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 1043 1044 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1045 if i == 1 { 1046 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 1047 if err != nil { 1048 t.Fatalf("failed to create tx: %v", err) 1049 } 1050 gen.AddTx(tx) 1051 } 1052 }) 1053 1054 // Spawn a goroutine to receive log events 1055 go validateLogEvent(logsCh, newLogCh, 1) 1056 if _, err := blockchain.InsertChain(chain); err != nil { 1057 t.Fatalf("failed to insert chain: %v", err) 1058 } 1059 if !<-newLogCh { 1060 t.Fatal("failed to receive new log event") 1061 } 1062 1063 // Generate long reorg chain 1064 forkChain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1065 if i == 1 { 1066 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 1067 if err != nil { 1068 t.Fatalf("failed to create tx: %v", err) 1069 } 1070 gen.AddTx(tx) 1071 // Higher block difficulty 1072 gen.OffsetTime(-9) 1073 } 1074 }) 1075 1076 // Spawn a goroutine to receive log events 1077 go validateLogEvent(logsCh, newLogCh, 1) 1078 go validateLogEvent(rmLogsCh, removeLogCh, 1) 1079 if _, err := blockchain.InsertChain(forkChain); err != nil { 1080 t.Fatalf("failed to insert forked chain: %v", err) 1081 } 1082 if !<-newLogCh { 1083 t.Fatal("failed to receive new log event") 1084 } 1085 if !<-removeLogCh { 1086 t.Fatal("failed to receive removed log event") 1087 } 1088 1089 newBlocks, _ := GenerateChain(params.TestChainConfig, chain[len(chain)-1], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) 1090 go validateLogEvent(logsCh, newLogCh, 1) 1091 go validateLogEvent(rmLogsCh, removeLogCh, 1) 1092 if _, err := blockchain.InsertChain(newBlocks); err != nil { 1093 t.Fatalf("failed to insert forked chain: %v", err) 1094 } 1095 // Rebirth logs should omit a newLogEvent 1096 if !<-newLogCh { 1097 t.Fatal("failed to receive new log event") 1098 } 1099 // Ensure removedLog events received 1100 if !<-removeLogCh { 1101 t.Fatal("failed to receive removed log event") 1102 } 1103 } 1104 1105 func TestSideLogRebirth(t *testing.T) { 1106 var ( 1107 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1108 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1109 db = rawdb.NewMemoryDatabase() 1110 1111 // this code generates a log 1112 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 1113 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 1114 genesis = gspec.MustCommit(db) 1115 signer = types.NewEIP155Signer(gspec.Config.ChainID) 1116 newLogCh = make(chan bool) 1117 ) 1118 1119 // listenNewLog checks whether the received logs number is equal with expected. 1120 listenNewLog := func(sink chan []*types.Log, expect int) { 1121 cnt := 0 1122 for { 1123 select { 1124 case logs := <-sink: 1125 cnt += len(logs) 1126 case <-time.NewTimer(5 * time.Second).C: 1127 // new logs timeout 1128 newLogCh <- false 1129 return 1130 } 1131 if cnt == expect { 1132 break 1133 } else if cnt > expect { 1134 // redundant logs received 1135 newLogCh <- false 1136 return 1137 } 1138 } 1139 select { 1140 case <-sink: 1141 // redundant logs received 1142 newLogCh <- false 1143 case <-time.NewTimer(100 * time.Millisecond).C: 1144 newLogCh <- true 1145 } 1146 } 1147 1148 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1149 defer blockchain.Stop() 1150 1151 logsCh := make(chan []*types.Log) 1152 blockchain.SubscribeLogsEvent(logsCh) 1153 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1154 if i == 1 { 1155 // Higher block difficulty 1156 gen.OffsetTime(-9) 1157 } 1158 }) 1159 if _, err := blockchain.InsertChain(chain); err != nil { 1160 t.Fatalf("failed to insert forked chain: %v", err) 1161 } 1162 1163 // Generate side chain with lower difficulty 1164 sideChain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1165 if i == 1 { 1166 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 1167 if err != nil { 1168 t.Fatalf("failed to create tx: %v", err) 1169 } 1170 gen.AddTx(tx) 1171 } 1172 }) 1173 if _, err := blockchain.InsertChain(sideChain); err != nil { 1174 t.Fatalf("failed to insert forked chain: %v", err) 1175 } 1176 1177 // Generate a new block based on side chain 1178 newBlocks, _ := GenerateChain(params.TestChainConfig, sideChain[len(sideChain)-1], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) 1179 go listenNewLog(logsCh, 1) 1180 if _, err := blockchain.InsertChain(newBlocks); err != nil { 1181 t.Fatalf("failed to insert forked chain: %v", err) 1182 } 1183 // Rebirth logs should omit a newLogEvent 1184 if !<-newLogCh { 1185 t.Fatalf("failed to receive new log event") 1186 } 1187 } 1188 1189 func TestReorgSideEvent(t *testing.T) { 1190 var ( 1191 db = rawdb.NewMemoryDatabase() 1192 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1193 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1194 gspec = &Genesis{ 1195 Config: params.TestChainConfig, 1196 Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}, 1197 } 1198 genesis = gspec.MustCommit(db) 1199 signer = types.NewEIP155Signer(gspec.Config.ChainID) 1200 ) 1201 1202 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1203 defer blockchain.Stop() 1204 1205 chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 1206 if _, err := blockchain.InsertChain(chain); err != nil { 1207 t.Fatalf("failed to insert chain: %v", err) 1208 } 1209 1210 replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) { 1211 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), nil), signer, key1) 1212 if i == 2 { 1213 gen.OffsetTime(-9) 1214 } 1215 if err != nil { 1216 t.Fatalf("failed to create tx: %v", err) 1217 } 1218 gen.AddTx(tx) 1219 }) 1220 chainSideCh := make(chan ChainSideEvent, 64) 1221 blockchain.SubscribeChainSideEvent(chainSideCh) 1222 if _, err := blockchain.InsertChain(replacementBlocks); err != nil { 1223 t.Fatalf("failed to insert chain: %v", err) 1224 } 1225 1226 // first two block of the secondary chain are for a brief moment considered 1227 // side chains because up to that point the first one is considered the 1228 // heavier chain. 1229 expectedSideHashes := map[common.Hash]bool{ 1230 replacementBlocks[0].Hash(): true, 1231 replacementBlocks[1].Hash(): true, 1232 chain[0].Hash(): true, 1233 chain[1].Hash(): true, 1234 chain[2].Hash(): true, 1235 } 1236 1237 i := 0 1238 1239 const timeoutDura = 10 * time.Second 1240 timeout := time.NewTimer(timeoutDura) 1241 done: 1242 for { 1243 select { 1244 case ev := <-chainSideCh: 1245 block := ev.Block 1246 if _, ok := expectedSideHashes[block.Hash()]; !ok { 1247 t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash()) 1248 } 1249 i++ 1250 1251 if i == len(expectedSideHashes) { 1252 timeout.Stop() 1253 1254 break done 1255 } 1256 timeout.Reset(timeoutDura) 1257 1258 case <-timeout.C: 1259 t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent") 1260 } 1261 } 1262 1263 // make sure no more events are fired 1264 select { 1265 case e := <-chainSideCh: 1266 t.Errorf("unexpected event fired: %v", e) 1267 case <-time.After(250 * time.Millisecond): 1268 } 1269 1270 } 1271 1272 // Tests if the canonical block can be fetched from the database during chain insertion. 1273 func TestCanonicalBlockRetrieval(t *testing.T) { 1274 _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) 1275 if err != nil { 1276 t.Fatalf("failed to create pristine chain: %v", err) 1277 } 1278 defer blockchain.Stop() 1279 1280 chain, _ := GenerateChain(blockchain.chainConfig, blockchain.genesisBlock, ethash.NewFaker(), blockchain.db, 10, func(i int, gen *BlockGen) {}) 1281 1282 var pend sync.WaitGroup 1283 pend.Add(len(chain)) 1284 1285 for i := range chain { 1286 go func(block *types.Block) { 1287 defer pend.Done() 1288 1289 // try to retrieve a block by its canonical hash and see if the block data can be retrieved. 1290 for { 1291 ch := rawdb.ReadCanonicalHash(blockchain.db, block.NumberU64()) 1292 if ch == (common.Hash{}) { 1293 continue // busy wait for canonical hash to be written 1294 } 1295 if ch != block.Hash() { 1296 t.Errorf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex()) 1297 return 1298 } 1299 fb := rawdb.ReadBlock(blockchain.db, ch, block.NumberU64()) 1300 if fb == nil { 1301 t.Errorf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex()) 1302 return 1303 } 1304 if fb.Hash() != block.Hash() { 1305 t.Errorf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex()) 1306 return 1307 } 1308 return 1309 } 1310 }(chain[i]) 1311 1312 if _, err := blockchain.InsertChain(types.Blocks{chain[i]}); err != nil { 1313 t.Fatalf("failed to insert block %d: %v", i, err) 1314 } 1315 } 1316 pend.Wait() 1317 } 1318 1319 func TestEIP155Transition(t *testing.T) { 1320 // Configure and generate a sample block chain 1321 var ( 1322 db = rawdb.NewMemoryDatabase() 1323 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1324 address = crypto.PubkeyToAddress(key.PublicKey) 1325 funds = big.NewInt(1000000000) 1326 deleteAddr = common.Address{1} 1327 gspec = &Genesis{ 1328 Config: ¶ms.ChainConfig{ChainID: big.NewInt(1), EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}, 1329 Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, 1330 } 1331 genesis = gspec.MustCommit(db) 1332 ) 1333 1334 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1335 defer blockchain.Stop() 1336 1337 blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1338 var ( 1339 tx *types.Transaction 1340 err error 1341 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1342 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1343 } 1344 ) 1345 switch i { 1346 case 0: 1347 tx, err = basicTx(types.HomesteadSigner{}) 1348 if err != nil { 1349 t.Fatal(err) 1350 } 1351 block.AddTx(tx) 1352 case 2: 1353 tx, err = basicTx(types.HomesteadSigner{}) 1354 if err != nil { 1355 t.Fatal(err) 1356 } 1357 block.AddTx(tx) 1358 1359 tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainID)) 1360 if err != nil { 1361 t.Fatal(err) 1362 } 1363 block.AddTx(tx) 1364 case 3: 1365 tx, err = basicTx(types.HomesteadSigner{}) 1366 if err != nil { 1367 t.Fatal(err) 1368 } 1369 block.AddTx(tx) 1370 1371 tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainID)) 1372 if err != nil { 1373 t.Fatal(err) 1374 } 1375 block.AddTx(tx) 1376 } 1377 }) 1378 1379 if _, err := blockchain.InsertChain(blocks); err != nil { 1380 t.Fatal(err) 1381 } 1382 block := blockchain.GetBlockByNumber(1) 1383 if block.Transactions()[0].Protected() { 1384 t.Error("Expected block[0].txs[0] to not be replay protected") 1385 } 1386 1387 block = blockchain.GetBlockByNumber(3) 1388 if block.Transactions()[0].Protected() { 1389 t.Error("Expected block[3].txs[0] to not be replay protected") 1390 } 1391 if !block.Transactions()[1].Protected() { 1392 t.Error("Expected block[3].txs[1] to be replay protected") 1393 } 1394 if _, err := blockchain.InsertChain(blocks[4:]); err != nil { 1395 t.Fatal(err) 1396 } 1397 1398 // generate an invalid chain id transaction 1399 config := ¶ms.ChainConfig{ChainID: big.NewInt(2), EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)} 1400 blocks, _ = GenerateChain(config, blocks[len(blocks)-1], ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1401 var ( 1402 tx *types.Transaction 1403 err error 1404 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1405 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1406 } 1407 ) 1408 if i == 0 { 1409 tx, err = basicTx(types.NewEIP155Signer(big.NewInt(2))) 1410 if err != nil { 1411 t.Fatal(err) 1412 } 1413 block.AddTx(tx) 1414 } 1415 }) 1416 _, err := blockchain.InsertChain(blocks) 1417 if err != types.ErrInvalidChainId { 1418 t.Error("expected error:", types.ErrInvalidChainId) 1419 } 1420 } 1421 1422 func TestEIP161AccountRemoval(t *testing.T) { 1423 // Configure and generate a sample block chain 1424 var ( 1425 db = rawdb.NewMemoryDatabase() 1426 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1427 address = crypto.PubkeyToAddress(key.PublicKey) 1428 funds = big.NewInt(1000000000) 1429 theAddr = common.Address{1} 1430 gspec = &Genesis{ 1431 Config: ¶ms.ChainConfig{ 1432 ChainID: big.NewInt(1), 1433 HomesteadBlock: new(big.Int), 1434 EIP155Block: new(big.Int), 1435 EIP150Block: new(big.Int), 1436 EIP158Block: big.NewInt(2), 1437 }, 1438 Alloc: GenesisAlloc{address: {Balance: funds}}, 1439 } 1440 genesis = gspec.MustCommit(db) 1441 ) 1442 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1443 defer blockchain.Stop() 1444 1445 blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, block *BlockGen) { 1446 var ( 1447 tx *types.Transaction 1448 err error 1449 signer = types.NewEIP155Signer(gspec.Config.ChainID) 1450 ) 1451 switch i { 1452 case 0: 1453 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1454 case 1: 1455 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1456 case 2: 1457 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1458 } 1459 if err != nil { 1460 t.Fatal(err) 1461 } 1462 block.AddTx(tx) 1463 }) 1464 // account must exist pre eip 161 1465 if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { 1466 t.Fatal(err) 1467 } 1468 if st, _ := blockchain.State(); !st.Exist(theAddr) { 1469 t.Error("expected account to exist") 1470 } 1471 1472 // account needs to be deleted post eip 161 1473 if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil { 1474 t.Fatal(err) 1475 } 1476 if st, _ := blockchain.State(); st.Exist(theAddr) { 1477 t.Error("account should not exist") 1478 } 1479 1480 // account musn't be created post eip 161 1481 if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil { 1482 t.Fatal(err) 1483 } 1484 if st, _ := blockchain.State(); st.Exist(theAddr) { 1485 t.Error("account should not exist") 1486 } 1487 } 1488 1489 // This is a regression test (i.e. as weird as it is, don't delete it ever), which 1490 // tests that under weird reorg conditions the blockchain and its internal header- 1491 // chain return the same latest block/header. 1492 // 1493 // https://github.com/ethereum/go-ethereum/pull/15941 1494 func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { 1495 // Generate a canonical chain to act as the main dataset 1496 engine := ethash.NewFaker() 1497 1498 db := rawdb.NewMemoryDatabase() 1499 genesis := new(Genesis).MustCommit(db) 1500 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1501 1502 // Generate a bunch of fork blocks, each side forking from the canonical chain 1503 forks := make([]*types.Block, len(blocks)) 1504 for i := 0; i < len(forks); i++ { 1505 parent := genesis 1506 if i > 0 { 1507 parent = blocks[i-1] 1508 } 1509 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1510 forks[i] = fork[0] 1511 } 1512 // Import the canonical and fork chain side by side, verifying the current block 1513 // and current header consistency 1514 diskdb := rawdb.NewMemoryDatabase() 1515 new(Genesis).MustCommit(diskdb) 1516 1517 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1518 if err != nil { 1519 t.Fatalf("failed to create tester chain: %v", err) 1520 } 1521 for i := 0; i < len(blocks); i++ { 1522 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1523 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1524 } 1525 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1526 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]) 1527 } 1528 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1529 t.Fatalf(" fork %d: failed to insert into chain: %v", i, err) 1530 } 1531 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1532 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]) 1533 } 1534 } 1535 } 1536 1537 // Tests that importing small side forks doesn't leave junk in the trie database 1538 // cache (which would eventually cause memory issues). 1539 func TestTrieForkGC(t *testing.T) { 1540 // Generate a canonical chain to act as the main dataset 1541 engine := ethash.NewFaker() 1542 1543 db := rawdb.NewMemoryDatabase() 1544 genesis := new(Genesis).MustCommit(db) 1545 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1546 1547 // Generate a bunch of fork blocks, each side forking from the canonical chain 1548 forks := make([]*types.Block, len(blocks)) 1549 for i := 0; i < len(forks); i++ { 1550 parent := genesis 1551 if i > 0 { 1552 parent = blocks[i-1] 1553 } 1554 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1555 forks[i] = fork[0] 1556 } 1557 // Import the canonical and fork chain side by side, forcing the trie cache to cache both 1558 diskdb := rawdb.NewMemoryDatabase() 1559 new(Genesis).MustCommit(diskdb) 1560 1561 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1562 if err != nil { 1563 t.Fatalf("failed to create tester chain: %v", err) 1564 } 1565 for i := 0; i < len(blocks); i++ { 1566 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1567 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1568 } 1569 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1570 t.Fatalf("fork %d: failed to insert into chain: %v", i, err) 1571 } 1572 } 1573 // Dereference all the recent tries and ensure no past trie is left in 1574 for i := 0; i < TriesInMemory; i++ { 1575 chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root()) 1576 chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root()) 1577 } 1578 if len(chain.stateCache.TrieDB().Nodes()) > 0 { 1579 t.Fatalf("stale tries still alive after garbase collection") 1580 } 1581 } 1582 1583 // Tests that doing large reorgs works even if the state associated with the 1584 // forking point is not available any more. 1585 func TestLargeReorgTrieGC(t *testing.T) { 1586 // Generate the original common chain segment and the two competing forks 1587 engine := ethash.NewFaker() 1588 1589 db := rawdb.NewMemoryDatabase() 1590 genesis := new(Genesis).MustCommit(db) 1591 1592 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1593 original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1594 competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*TriesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) 1595 1596 // Import the shared chain and the original canonical one 1597 diskdb := rawdb.NewMemoryDatabase() 1598 new(Genesis).MustCommit(diskdb) 1599 1600 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1601 if err != nil { 1602 t.Fatalf("failed to create tester chain: %v", err) 1603 } 1604 if _, err := chain.InsertChain(shared); err != nil { 1605 t.Fatalf("failed to insert shared chain: %v", err) 1606 } 1607 if _, err := chain.InsertChain(original); err != nil { 1608 t.Fatalf("failed to insert original chain: %v", err) 1609 } 1610 // Ensure that the state associated with the forking point is pruned away 1611 if node, _ := chain.stateCache.TrieDB().Node(shared[len(shared)-1].Root()); node != nil { 1612 t.Fatalf("common-but-old ancestor still cache") 1613 } 1614 // Import the competitor chain without exceeding the canonical's TD and ensure 1615 // we have not processed any of the blocks (protection against malicious blocks) 1616 if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil { 1617 t.Fatalf("failed to insert competitor chain: %v", err) 1618 } 1619 for i, block := range competitor[:len(competitor)-2] { 1620 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1621 t.Fatalf("competitor %d: low TD chain became processed", i) 1622 } 1623 } 1624 // Import the head of the competitor chain, triggering the reorg and ensure we 1625 // successfully reprocess all the stashed away blocks. 1626 if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil { 1627 t.Fatalf("failed to finalize competitor chain: %v", err) 1628 } 1629 for i, block := range competitor[:len(competitor)-TriesInMemory] { 1630 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1631 t.Fatalf("competitor %d: competing chain state missing", i) 1632 } 1633 } 1634 } 1635 1636 func TestBlockchainRecovery(t *testing.T) { 1637 // Configure and generate a sample block chain 1638 var ( 1639 gendb = rawdb.NewMemoryDatabase() 1640 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1641 address = crypto.PubkeyToAddress(key.PublicKey) 1642 funds = big.NewInt(1000000000) 1643 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 1644 genesis = gspec.MustCommit(gendb) 1645 ) 1646 height := uint64(1024) 1647 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil) 1648 1649 // Import the chain as a ancient-first node and ensure all pointers are updated 1650 frdir, err := ioutil.TempDir("", "") 1651 if err != nil { 1652 t.Fatalf("failed to create temp freezer dir: %v", err) 1653 } 1654 defer os.Remove(frdir) 1655 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "") 1656 if err != nil { 1657 t.Fatalf("failed to create temp freezer db: %v", err) 1658 } 1659 gspec.MustCommit(ancientDb) 1660 ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1661 1662 headers := make([]*types.Header, len(blocks)) 1663 for i, block := range blocks { 1664 headers[i] = block.Header() 1665 } 1666 if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { 1667 t.Fatalf("failed to insert header %d: %v", n, err) 1668 } 1669 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { 1670 t.Fatalf("failed to insert receipt %d: %v", n, err) 1671 } 1672 ancient.Stop() 1673 1674 // Destroy head fast block manually 1675 midBlock := blocks[len(blocks)/2] 1676 rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash()) 1677 1678 // Reopen broken blockchain again 1679 ancient, _ = NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1680 defer ancient.Stop() 1681 if num := ancient.CurrentBlock().NumberU64(); num != 0 { 1682 t.Errorf("head block mismatch: have #%v, want #%v", num, 0) 1683 } 1684 if num := ancient.CurrentFastBlock().NumberU64(); num != midBlock.NumberU64() { 1685 t.Errorf("head fast-block mismatch: have #%v, want #%v", num, midBlock.NumberU64()) 1686 } 1687 if num := ancient.CurrentHeader().Number.Uint64(); num != midBlock.NumberU64() { 1688 t.Errorf("head header mismatch: have #%v, want #%v", num, midBlock.NumberU64()) 1689 } 1690 } 1691 1692 func TestIncompleteAncientReceiptChainInsertion(t *testing.T) { 1693 // Configure and generate a sample block chain 1694 var ( 1695 gendb = rawdb.NewMemoryDatabase() 1696 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1697 address = crypto.PubkeyToAddress(key.PublicKey) 1698 funds = big.NewInt(1000000000) 1699 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 1700 genesis = gspec.MustCommit(gendb) 1701 ) 1702 height := uint64(1024) 1703 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil) 1704 1705 // Import the chain as a ancient-first node and ensure all pointers are updated 1706 frdir, err := ioutil.TempDir("", "") 1707 if err != nil { 1708 t.Fatalf("failed to create temp freezer dir: %v", err) 1709 } 1710 defer os.Remove(frdir) 1711 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "") 1712 if err != nil { 1713 t.Fatalf("failed to create temp freezer db: %v", err) 1714 } 1715 gspec.MustCommit(ancientDb) 1716 ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) 1717 defer ancient.Stop() 1718 1719 headers := make([]*types.Header, len(blocks)) 1720 for i, block := range blocks { 1721 headers[i] = block.Header() 1722 } 1723 if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { 1724 t.Fatalf("failed to insert header %d: %v", n, err) 1725 } 1726 // Abort ancient receipt chain insertion deliberately 1727 ancient.terminateInsert = func(hash common.Hash, number uint64) bool { 1728 return number == blocks[len(blocks)/2].NumberU64() 1729 } 1730 previousFastBlock := ancient.CurrentFastBlock() 1731 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err == nil { 1732 t.Fatalf("failed to insert receipt %d: %v", n, err) 1733 } 1734 if ancient.CurrentFastBlock().NumberU64() != previousFastBlock.NumberU64() { 1735 t.Fatalf("failed to rollback ancient data, want %d, have %d", previousFastBlock.NumberU64(), ancient.CurrentFastBlock().NumberU64()) 1736 } 1737 if frozen, err := ancient.db.Ancients(); err != nil || frozen != 1 { 1738 t.Fatalf("failed to truncate ancient data") 1739 } 1740 ancient.terminateInsert = nil 1741 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { 1742 t.Fatalf("failed to insert receipt %d: %v", n, err) 1743 } 1744 if ancient.CurrentFastBlock().NumberU64() != blocks[len(blocks)-1].NumberU64() { 1745 t.Fatalf("failed to insert ancient recept chain after rollback") 1746 } 1747 } 1748 1749 // Tests that importing a very large side fork, which is larger than the canon chain, 1750 // but where the difficulty per block is kept low: this means that it will not 1751 // overtake the 'canon' chain until after it's passed canon by about 200 blocks. 1752 // 1753 // Details at: 1754 // - https://github.com/ethereum/go-ethereum/issues/18977 1755 // - https://github.com/ethereum/go-ethereum/pull/18988 1756 func TestLowDiffLongChain(t *testing.T) { 1757 // Generate a canonical chain to act as the main dataset 1758 engine := ethash.NewFaker() 1759 db := rawdb.NewMemoryDatabase() 1760 genesis := new(Genesis).MustCommit(db) 1761 1762 // We must use a pretty long chain to ensure that the fork doesn't overtake us 1763 // until after at least 128 blocks post tip 1764 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 6*TriesInMemory, func(i int, b *BlockGen) { 1765 b.SetCoinbase(common.Address{1}) 1766 b.OffsetTime(-9) 1767 }) 1768 1769 // Import the canonical chain 1770 diskdb := rawdb.NewMemoryDatabase() 1771 new(Genesis).MustCommit(diskdb) 1772 1773 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1774 if err != nil { 1775 t.Fatalf("failed to create tester chain: %v", err) 1776 } 1777 if n, err := chain.InsertChain(blocks); err != nil { 1778 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 1779 } 1780 // Generate fork chain, starting from an early block 1781 parent := blocks[10] 1782 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 8*TriesInMemory, func(i int, b *BlockGen) { 1783 b.SetCoinbase(common.Address{2}) 1784 }) 1785 1786 // And now import the fork 1787 if i, err := chain.InsertChain(fork); err != nil { 1788 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1789 } 1790 head := chain.CurrentBlock() 1791 if got := fork[len(fork)-1].Hash(); got != head.Hash() { 1792 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 1793 } 1794 // Sanity check that all the canonical numbers are present 1795 header := chain.CurrentHeader() 1796 for number := head.NumberU64(); number > 0; number-- { 1797 if hash := chain.GetHeaderByNumber(number).Hash(); hash != header.Hash() { 1798 t.Fatalf("header %d: canonical hash mismatch: have %x, want %x", number, hash, header.Hash()) 1799 } 1800 header = chain.GetHeader(header.ParentHash, number-1) 1801 } 1802 } 1803 1804 // Tests that importing a sidechain (S), where 1805 // - S is sidechain, containing blocks [Sn...Sm] 1806 // - C is canon chain, containing blocks [G..Cn..Cm] 1807 // - A common ancestor is placed at prune-point + blocksBetweenCommonAncestorAndPruneblock 1808 // - The sidechain S is prepended with numCanonBlocksInSidechain blocks from the canon chain 1809 func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommonAncestorAndPruneblock int) { 1810 1811 // Generate a canonical chain to act as the main dataset 1812 engine := ethash.NewFaker() 1813 db := rawdb.NewMemoryDatabase() 1814 genesis := new(Genesis).MustCommit(db) 1815 1816 // Generate and import the canonical chain 1817 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, nil) 1818 diskdb := rawdb.NewMemoryDatabase() 1819 new(Genesis).MustCommit(diskdb) 1820 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1821 if err != nil { 1822 t.Fatalf("failed to create tester chain: %v", err) 1823 } 1824 if n, err := chain.InsertChain(blocks); err != nil { 1825 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 1826 } 1827 1828 lastPrunedIndex := len(blocks) - TriesInMemory - 1 1829 lastPrunedBlock := blocks[lastPrunedIndex] 1830 firstNonPrunedBlock := blocks[len(blocks)-TriesInMemory] 1831 1832 // Verify pruning of lastPrunedBlock 1833 if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) { 1834 t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64()) 1835 } 1836 // Verify firstNonPrunedBlock is not pruned 1837 if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) { 1838 t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64()) 1839 } 1840 // Generate the sidechain 1841 // First block should be a known block, block after should be a pruned block. So 1842 // canon(pruned), side, side... 1843 1844 // Generate fork chain, make it longer than canon 1845 parentIndex := lastPrunedIndex + blocksBetweenCommonAncestorAndPruneblock 1846 parent := blocks[parentIndex] 1847 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { 1848 b.SetCoinbase(common.Address{2}) 1849 }) 1850 // Prepend the parent(s) 1851 var sidechain []*types.Block 1852 for i := numCanonBlocksInSidechain; i > 0; i-- { 1853 sidechain = append(sidechain, blocks[parentIndex+1-i]) 1854 } 1855 sidechain = append(sidechain, fork...) 1856 _, err = chain.InsertChain(sidechain) 1857 if err != nil { 1858 t.Errorf("Got error, %v", err) 1859 } 1860 head := chain.CurrentBlock() 1861 if got := fork[len(fork)-1].Hash(); got != head.Hash() { 1862 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 1863 } 1864 } 1865 1866 // Tests that importing a sidechain (S), where 1867 // - S is sidechain, containing blocks [Sn...Sm] 1868 // - C is canon chain, containing blocks [G..Cn..Cm] 1869 // - The common ancestor Cc is pruned 1870 // - The first block in S: Sn, is == Cn 1871 // That is: the sidechain for import contains some blocks already present in canon chain. 1872 // So the blocks are 1873 // [ Cn, Cn+1, Cc, Sn+3 ... Sm] 1874 // ^ ^ ^ pruned 1875 func TestPrunedImportSide(t *testing.T) { 1876 //glogger := log.NewGlogHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false))) 1877 //glogger.Verbosity(3) 1878 //log.Root().SetHandler(log.Handler(glogger)) 1879 testSideImport(t, 3, 3) 1880 testSideImport(t, 3, -3) 1881 testSideImport(t, 10, 0) 1882 testSideImport(t, 1, 10) 1883 testSideImport(t, 1, -10) 1884 } 1885 1886 func TestInsertKnownHeaders(t *testing.T) { testInsertKnownChainData(t, "headers") } 1887 func TestInsertKnownReceiptChain(t *testing.T) { testInsertKnownChainData(t, "receipts") } 1888 func TestInsertKnownBlocks(t *testing.T) { testInsertKnownChainData(t, "blocks") } 1889 1890 func testInsertKnownChainData(t *testing.T, typ string) { 1891 engine := ethash.NewFaker() 1892 1893 db := rawdb.NewMemoryDatabase() 1894 genesis := new(Genesis).MustCommit(db) 1895 1896 blocks, receipts := GenerateChain(params.TestChainConfig, genesis, engine, db, 32, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1897 // A longer chain but total difficulty is lower. 1898 blocks2, receipts2 := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], engine, db, 65, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1899 // A shorter chain but total difficulty is higher. 1900 blocks3, receipts3 := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], engine, db, 64, func(i int, b *BlockGen) { 1901 b.SetCoinbase(common.Address{1}) 1902 b.OffsetTime(-9) // A higher difficulty 1903 }) 1904 // Import the shared chain and the original canonical one 1905 dir, err := ioutil.TempDir("", "") 1906 if err != nil { 1907 t.Fatalf("failed to create temp freezer dir: %v", err) 1908 } 1909 defer os.Remove(dir) 1910 chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), dir, "") 1911 if err != nil { 1912 t.Fatalf("failed to create temp freezer db: %v", err) 1913 } 1914 new(Genesis).MustCommit(chaindb) 1915 defer os.RemoveAll(dir) 1916 1917 chain, err := NewBlockChain(chaindb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 1918 if err != nil { 1919 t.Fatalf("failed to create tester chain: %v", err) 1920 } 1921 1922 var ( 1923 inserter func(blocks []*types.Block, receipts []types.Receipts) error 1924 asserter func(t *testing.T, block *types.Block) 1925 ) 1926 if typ == "headers" { 1927 inserter = func(blocks []*types.Block, receipts []types.Receipts) error { 1928 headers := make([]*types.Header, 0, len(blocks)) 1929 for _, block := range blocks { 1930 headers = append(headers, block.Header()) 1931 } 1932 _, err := chain.InsertHeaderChain(headers, 1) 1933 return err 1934 } 1935 asserter = func(t *testing.T, block *types.Block) { 1936 if chain.CurrentHeader().Hash() != block.Hash() { 1937 t.Fatalf("current head header mismatch, have %v, want %v", chain.CurrentHeader().Hash().Hex(), block.Hash().Hex()) 1938 } 1939 } 1940 } else if typ == "receipts" { 1941 inserter = func(blocks []*types.Block, receipts []types.Receipts) error { 1942 headers := make([]*types.Header, 0, len(blocks)) 1943 for _, block := range blocks { 1944 headers = append(headers, block.Header()) 1945 } 1946 _, err := chain.InsertHeaderChain(headers, 1) 1947 if err != nil { 1948 return err 1949 } 1950 _, err = chain.InsertReceiptChain(blocks, receipts, 0) 1951 return err 1952 } 1953 asserter = func(t *testing.T, block *types.Block) { 1954 if chain.CurrentFastBlock().Hash() != block.Hash() { 1955 t.Fatalf("current head fast block mismatch, have %v, want %v", chain.CurrentFastBlock().Hash().Hex(), block.Hash().Hex()) 1956 } 1957 } 1958 } else { 1959 inserter = func(blocks []*types.Block, receipts []types.Receipts) error { 1960 _, err := chain.InsertChain(blocks) 1961 return err 1962 } 1963 asserter = func(t *testing.T, block *types.Block) { 1964 if chain.CurrentBlock().Hash() != block.Hash() { 1965 t.Fatalf("current head block mismatch, have %v, want %v", chain.CurrentBlock().Hash().Hex(), block.Hash().Hex()) 1966 } 1967 } 1968 } 1969 1970 if err := inserter(blocks, receipts); err != nil { 1971 t.Fatalf("failed to insert chain data: %v", err) 1972 } 1973 1974 // Reimport the chain data again. All the imported 1975 // chain data are regarded "known" data. 1976 if err := inserter(blocks, receipts); err != nil { 1977 t.Fatalf("failed to insert chain data: %v", err) 1978 } 1979 asserter(t, blocks[len(blocks)-1]) 1980 1981 // Import a long canonical chain with some known data as prefix. 1982 var rollback []common.Hash 1983 for i := len(blocks) / 2; i < len(blocks); i++ { 1984 rollback = append(rollback, blocks[i].Hash()) 1985 } 1986 chain.Rollback(rollback) 1987 if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { 1988 t.Fatalf("failed to insert chain data: %v", err) 1989 } 1990 asserter(t, blocks2[len(blocks2)-1]) 1991 1992 // Import a heavier shorter but higher total difficulty chain with some known data as prefix. 1993 if err := inserter(append(blocks, blocks3...), append(receipts, receipts3...)); err != nil { 1994 t.Fatalf("failed to insert chain data: %v", err) 1995 } 1996 asserter(t, blocks3[len(blocks3)-1]) 1997 1998 // Import a longer but lower total difficulty chain with some known data as prefix. 1999 if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { 2000 t.Fatalf("failed to insert chain data: %v", err) 2001 } 2002 // The head shouldn't change. 2003 asserter(t, blocks3[len(blocks3)-1]) 2004 2005 // Rollback the heavier chain and re-insert the longer chain again 2006 for i := 0; i < len(blocks3); i++ { 2007 rollback = append(rollback, blocks3[i].Hash()) 2008 } 2009 chain.Rollback(rollback) 2010 2011 if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { 2012 t.Fatalf("failed to insert chain data: %v", err) 2013 } 2014 asserter(t, blocks2[len(blocks2)-1]) 2015 } 2016 2017 // getLongAndShortChains returns two chains, 2018 // A is longer, B is heavier 2019 func getLongAndShortChains() (*BlockChain, []*types.Block, []*types.Block, error) { 2020 // Generate a canonical chain to act as the main dataset 2021 engine := ethash.NewFaker() 2022 db := rawdb.NewMemoryDatabase() 2023 genesis := new(Genesis).MustCommit(db) 2024 2025 // Generate and import the canonical chain, 2026 // Offset the time, to keep the difficulty low 2027 longChain, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 80, func(i int, b *BlockGen) { 2028 b.SetCoinbase(common.Address{1}) 2029 }) 2030 diskdb := rawdb.NewMemoryDatabase() 2031 new(Genesis).MustCommit(diskdb) 2032 2033 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 2034 if err != nil { 2035 return nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err) 2036 } 2037 2038 // Generate fork chain, make it shorter than canon, with common ancestor pretty early 2039 parentIndex := 3 2040 parent := longChain[parentIndex] 2041 heavyChain, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 75, func(i int, b *BlockGen) { 2042 b.SetCoinbase(common.Address{2}) 2043 b.OffsetTime(-9) 2044 }) 2045 // Verify that the test is sane 2046 var ( 2047 longerTd = new(big.Int) 2048 shorterTd = new(big.Int) 2049 ) 2050 for index, b := range longChain { 2051 longerTd.Add(longerTd, b.Difficulty()) 2052 if index <= parentIndex { 2053 shorterTd.Add(shorterTd, b.Difficulty()) 2054 } 2055 } 2056 for _, b := range heavyChain { 2057 shorterTd.Add(shorterTd, b.Difficulty()) 2058 } 2059 if shorterTd.Cmp(longerTd) <= 0 { 2060 return nil, nil, nil, fmt.Errorf("Test is moot, heavyChain td (%v) must be larger than canon td (%v)", shorterTd, longerTd) 2061 } 2062 longerNum := longChain[len(longChain)-1].NumberU64() 2063 shorterNum := heavyChain[len(heavyChain)-1].NumberU64() 2064 if shorterNum >= longerNum { 2065 return nil, nil, nil, fmt.Errorf("Test is moot, heavyChain num (%v) must be lower than canon num (%v)", shorterNum, longerNum) 2066 } 2067 return chain, longChain, heavyChain, nil 2068 } 2069 2070 // TestReorgToShorterRemovesCanonMapping tests that if we 2071 // 1. Have a chain [0 ... N .. X] 2072 // 2. Reorg to shorter but heavier chain [0 ... N ... Y] 2073 // 3. Then there should be no canon mapping for the block at height X 2074 func TestReorgToShorterRemovesCanonMapping(t *testing.T) { 2075 chain, canonblocks, sideblocks, err := getLongAndShortChains() 2076 if err != nil { 2077 t.Fatal(err) 2078 } 2079 if n, err := chain.InsertChain(canonblocks); err != nil { 2080 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2081 } 2082 canonNum := chain.CurrentBlock().NumberU64() 2083 _, err = chain.InsertChain(sideblocks) 2084 if err != nil { 2085 t.Errorf("Got error, %v", err) 2086 } 2087 head := chain.CurrentBlock() 2088 if got := sideblocks[len(sideblocks)-1].Hash(); got != head.Hash() { 2089 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 2090 } 2091 // We have now inserted a sidechain. 2092 if blockByNum := chain.GetBlockByNumber(canonNum); blockByNum != nil { 2093 t.Errorf("expected block to be gone: %v", blockByNum.NumberU64()) 2094 } 2095 if headerByNum := chain.GetHeaderByNumber(canonNum); headerByNum != nil { 2096 t.Errorf("expected header to be gone: %v", headerByNum.Number.Uint64()) 2097 } 2098 } 2099 2100 // TestReorgToShorterRemovesCanonMappingHeaderChain is the same scenario 2101 // as TestReorgToShorterRemovesCanonMapping, but applied on headerchain 2102 // imports -- that is, for fast sync 2103 func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) { 2104 chain, canonblocks, sideblocks, err := getLongAndShortChains() 2105 if err != nil { 2106 t.Fatal(err) 2107 } 2108 // Convert into headers 2109 canonHeaders := make([]*types.Header, len(canonblocks)) 2110 for i, block := range canonblocks { 2111 canonHeaders[i] = block.Header() 2112 } 2113 if n, err := chain.InsertHeaderChain(canonHeaders, 0); err != nil { 2114 t.Fatalf("header %d: failed to insert into chain: %v", n, err) 2115 } 2116 canonNum := chain.CurrentHeader().Number.Uint64() 2117 sideHeaders := make([]*types.Header, len(sideblocks)) 2118 for i, block := range sideblocks { 2119 sideHeaders[i] = block.Header() 2120 } 2121 if n, err := chain.InsertHeaderChain(sideHeaders, 0); err != nil { 2122 t.Fatalf("header %d: failed to insert into chain: %v", n, err) 2123 } 2124 head := chain.CurrentHeader() 2125 if got := sideblocks[len(sideblocks)-1].Hash(); got != head.Hash() { 2126 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 2127 } 2128 // We have now inserted a sidechain. 2129 if blockByNum := chain.GetBlockByNumber(canonNum); blockByNum != nil { 2130 t.Errorf("expected block to be gone: %v", blockByNum.NumberU64()) 2131 } 2132 if headerByNum := chain.GetHeaderByNumber(canonNum); headerByNum != nil { 2133 t.Errorf("expected header to be gone: %v", headerByNum.Number.Uint64()) 2134 } 2135 } 2136 2137 // Benchmarks large blocks with value transfers to non-existing accounts 2138 func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) { 2139 var ( 2140 signer = types.HomesteadSigner{} 2141 testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 2142 testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) 2143 bankFunds = big.NewInt(100000000000000000) 2144 gspec = Genesis{ 2145 Config: params.TestChainConfig, 2146 Alloc: GenesisAlloc{ 2147 testBankAddress: {Balance: bankFunds}, 2148 common.HexToAddress("0xc0de"): { 2149 Code: []byte{0x60, 0x01, 0x50}, 2150 Balance: big.NewInt(0), 2151 }, // push 1, pop 2152 }, 2153 GasLimit: 100e6, // 100 M 2154 } 2155 ) 2156 // Generate the original common chain segment and the two competing forks 2157 engine := ethash.NewFaker() 2158 db := rawdb.NewMemoryDatabase() 2159 genesis := gspec.MustCommit(db) 2160 2161 blockGenerator := func(i int, block *BlockGen) { 2162 block.SetCoinbase(common.Address{1}) 2163 for txi := 0; txi < numTxs; txi++ { 2164 uniq := uint64(i*numTxs + txi) 2165 recipient := recipientFn(uniq) 2166 tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxGas, big.NewInt(1), nil), signer, testBankKey) 2167 if err != nil { 2168 b.Error(err) 2169 } 2170 block.AddTx(tx) 2171 } 2172 } 2173 2174 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, numBlocks, blockGenerator) 2175 b.StopTimer() 2176 b.ResetTimer() 2177 for i := 0; i < b.N; i++ { 2178 // Import the shared chain and the original canonical one 2179 diskdb := rawdb.NewMemoryDatabase() 2180 gspec.MustCommit(diskdb) 2181 2182 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 2183 if err != nil { 2184 b.Fatalf("failed to create tester chain: %v", err) 2185 } 2186 b.StartTimer() 2187 if _, err := chain.InsertChain(shared); err != nil { 2188 b.Fatalf("failed to insert shared chain: %v", err) 2189 } 2190 b.StopTimer() 2191 if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks { 2192 b.Fatalf("Transactions were not included, expected %d, got %d", numTxs*numBlocks, got) 2193 2194 } 2195 } 2196 } 2197 2198 func BenchmarkBlockChain_1x1000ValueTransferToNonexisting(b *testing.B) { 2199 var ( 2200 numTxs = 1000 2201 numBlocks = 1 2202 ) 2203 recipientFn := func(nonce uint64) common.Address { 2204 return common.BigToAddress(big.NewInt(0).SetUint64(1337 + nonce)) 2205 } 2206 dataFn := func(nonce uint64) []byte { 2207 return nil 2208 } 2209 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 2210 } 2211 2212 func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) { 2213 var ( 2214 numTxs = 1000 2215 numBlocks = 1 2216 ) 2217 b.StopTimer() 2218 b.ResetTimer() 2219 2220 recipientFn := func(nonce uint64) common.Address { 2221 return common.BigToAddress(big.NewInt(0).SetUint64(1337)) 2222 } 2223 dataFn := func(nonce uint64) []byte { 2224 return nil 2225 } 2226 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 2227 } 2228 2229 func BenchmarkBlockChain_1x1000Executions(b *testing.B) { 2230 var ( 2231 numTxs = 1000 2232 numBlocks = 1 2233 ) 2234 b.StopTimer() 2235 b.ResetTimer() 2236 2237 recipientFn := func(nonce uint64) common.Address { 2238 return common.BigToAddress(big.NewInt(0).SetUint64(0xc0de)) 2239 } 2240 dataFn := func(nonce uint64) []byte { 2241 return nil 2242 } 2243 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 2244 } 2245 2246 // Tests that importing a some old blocks, where all blocks are before the 2247 // pruning point. 2248 // This internally leads to a sidechain import, since the blocks trigger an 2249 // ErrPrunedAncestor error. 2250 // This may e.g. happen if 2251 // 1. Downloader rollbacks a batch of inserted blocks and exits 2252 // 2. Downloader starts to sync again 2253 // 3. The blocks fetched are all known and canonical blocks 2254 func TestSideImportPrunedBlocks(t *testing.T) { 2255 // Generate a canonical chain to act as the main dataset 2256 engine := ethash.NewFaker() 2257 db := rawdb.NewMemoryDatabase() 2258 genesis := new(Genesis).MustCommit(db) 2259 2260 // Generate and import the canonical chain 2261 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, nil) 2262 diskdb := rawdb.NewMemoryDatabase() 2263 new(Genesis).MustCommit(diskdb) 2264 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 2265 if err != nil { 2266 t.Fatalf("failed to create tester chain: %v", err) 2267 } 2268 if n, err := chain.InsertChain(blocks); err != nil { 2269 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2270 } 2271 2272 lastPrunedIndex := len(blocks) - TriesInMemory - 1 2273 lastPrunedBlock := blocks[lastPrunedIndex] 2274 2275 // Verify pruning of lastPrunedBlock 2276 if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) { 2277 t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64()) 2278 } 2279 firstNonPrunedBlock := blocks[len(blocks)-TriesInMemory] 2280 // Verify firstNonPrunedBlock is not pruned 2281 if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) { 2282 t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64()) 2283 } 2284 // Now re-import some old blocks 2285 blockToReimport := blocks[5:8] 2286 _, err = chain.InsertChain(blockToReimport) 2287 if err != nil { 2288 t.Errorf("Got error, %v", err) 2289 } 2290 } 2291 2292 // TestDeleteCreateRevert tests a weird state transition corner case that we hit 2293 // while changing the internals of statedb. The workflow is that a contract is 2294 // self destructed, then in a followup transaction (but same block) it's created 2295 // again and the transaction reverted. 2296 // 2297 // The original statedb implementation flushed dirty objects to the tries after 2298 // each transaction, so this works ok. The rework accumulated writes in memory 2299 // first, but the journal wiped the entire state object on create-revert. 2300 func TestDeleteCreateRevert(t *testing.T) { 2301 var ( 2302 aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") 2303 bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb") 2304 // Generate a canonical chain to act as the main dataset 2305 engine = ethash.NewFaker() 2306 db = rawdb.NewMemoryDatabase() 2307 2308 // A sender who makes transactions, has some funds 2309 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 2310 address = crypto.PubkeyToAddress(key.PublicKey) 2311 funds = big.NewInt(1000000000) 2312 gspec = &Genesis{ 2313 Config: params.TestChainConfig, 2314 Alloc: GenesisAlloc{ 2315 address: {Balance: funds}, 2316 // The address 0xAAAAA selfdestructs if called 2317 aa: { 2318 // Code needs to just selfdestruct 2319 Code: []byte{byte(vm.PC), 0xFF}, 2320 Nonce: 1, 2321 Balance: big.NewInt(0), 2322 }, 2323 // The address 0xBBBB send 1 wei to 0xAAAA, then reverts 2324 bb: { 2325 Code: []byte{ 2326 byte(vm.PC), // [0] 2327 byte(vm.DUP1), // [0,0] 2328 byte(vm.DUP1), // [0,0,0] 2329 byte(vm.DUP1), // [0,0,0,0] 2330 byte(vm.PUSH1), 0x01, // [0,0,0,0,1] (value) 2331 byte(vm.PUSH2), 0xaa, 0xaa, // [0,0,0,0,1, 0xaaaa] 2332 byte(vm.GAS), 2333 byte(vm.CALL), 2334 byte(vm.REVERT), 2335 }, 2336 Balance: big.NewInt(1), 2337 }, 2338 }, 2339 } 2340 genesis = gspec.MustCommit(db) 2341 ) 2342 2343 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 1, func(i int, b *BlockGen) { 2344 b.SetCoinbase(common.Address{1}) 2345 // One transaction to AAAA 2346 tx, _ := types.SignTx(types.NewTransaction(0, aa, 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, big.NewInt(0), 100000, big.NewInt(1), nil), types.HomesteadSigner{}, key) 2350 b.AddTx(tx) 2351 }) 2352 // Import the canonical chain 2353 diskdb := rawdb.NewMemoryDatabase() 2354 gspec.MustCommit(diskdb) 2355 2356 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) 2357 if err != nil { 2358 t.Fatalf("failed to create tester chain: %v", err) 2359 } 2360 if n, err := chain.InsertChain(blocks); err != nil { 2361 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2362 } 2363 }