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