github.com/4000d/go-ethereum@v1.8.2-0.20180223170251-423c8bb1d821/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 "math/big" 22 "math/rand" 23 "sync" 24 "testing" 25 "time" 26 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/consensus/ethash" 29 "github.com/ethereum/go-ethereum/core/state" 30 "github.com/ethereum/go-ethereum/core/types" 31 "github.com/ethereum/go-ethereum/core/vm" 32 "github.com/ethereum/go-ethereum/crypto" 33 "github.com/ethereum/go-ethereum/ethdb" 34 "github.com/ethereum/go-ethereum/params" 35 ) 36 37 // Test fork of length N starting from block i 38 func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) { 39 // Copy old chain up to #i into a new db 40 db, blockchain2, err := newCanonical(ethash.NewFaker(), i, full) 41 if err != nil { 42 t.Fatal("could not make new canonical in testFork", err) 43 } 44 defer blockchain2.Stop() 45 46 // Assert the chains have the same header/block at #i 47 var hash1, hash2 common.Hash 48 if full { 49 hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash() 50 hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash() 51 } else { 52 hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash() 53 hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash() 54 } 55 if hash1 != hash2 { 56 t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) 57 } 58 // Extend the newly created chain 59 var ( 60 blockChainB []*types.Block 61 headerChainB []*types.Header 62 ) 63 if full { 64 blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed) 65 if _, err := blockchain2.InsertChain(blockChainB); err != nil { 66 t.Fatalf("failed to insert forking chain: %v", err) 67 } 68 } else { 69 headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, ethash.NewFaker(), db, forkSeed) 70 if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil { 71 t.Fatalf("failed to insert forking chain: %v", err) 72 } 73 } 74 // Sanity check that the forked chain can be imported into the original 75 var tdPre, tdPost *big.Int 76 77 if full { 78 tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()) 79 if err := testBlockChainImport(blockChainB, blockchain); err != nil { 80 t.Fatalf("failed to import forked block chain: %v", err) 81 } 82 tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash()) 83 } else { 84 tdPre = blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()) 85 if err := testHeaderChainImport(headerChainB, blockchain); err != nil { 86 t.Fatalf("failed to import forked header chain: %v", err) 87 } 88 tdPost = blockchain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash()) 89 } 90 // Compare the total difficulties of the chains 91 comparator(tdPre, tdPost) 92 } 93 94 func printChain(bc *BlockChain) { 95 for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- { 96 b := bc.GetBlockByNumber(uint64(i)) 97 fmt.Printf("\t%x %v\n", b.Hash(), b.Difficulty()) 98 } 99 } 100 101 // testBlockChainImport tries to process a chain of blocks, writing them into 102 // the database if successful. 103 func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { 104 for _, block := range chain { 105 // Try and process the block 106 err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) 107 if err == nil { 108 err = blockchain.validator.ValidateBody(block) 109 } 110 if err != nil { 111 if err == ErrKnownBlock { 112 continue 113 } 114 return err 115 } 116 statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache) 117 if err != nil { 118 return err 119 } 120 receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, vm.Config{}) 121 if err != nil { 122 blockchain.reportBlock(block, receipts, err) 123 return err 124 } 125 err = blockchain.validator.ValidateState(block, blockchain.GetBlockByHash(block.ParentHash()), statedb, receipts, usedGas) 126 if err != nil { 127 blockchain.reportBlock(block, receipts, err) 128 return err 129 } 130 blockchain.mu.Lock() 131 WriteTd(blockchain.db, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash()))) 132 WriteBlock(blockchain.db, block) 133 statedb.Commit(false) 134 blockchain.mu.Unlock() 135 } 136 return nil 137 } 138 139 // testHeaderChainImport tries to process a chain of header, writing them into 140 // the database if successful. 141 func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { 142 for _, header := range chain { 143 // Try and validate the header 144 if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil { 145 return err 146 } 147 // Manually insert the header into the database, but don't reorganise (allows subsequent testing) 148 blockchain.mu.Lock() 149 WriteTd(blockchain.db, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash))) 150 WriteHeader(blockchain.db, header) 151 blockchain.mu.Unlock() 152 } 153 return nil 154 } 155 156 func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *testing.T) { 157 _, err := blockchain.InsertChain(chain) 158 if err != nil { 159 fmt.Println(err) 160 t.FailNow() 161 } 162 done <- true 163 } 164 165 func TestLastBlock(t *testing.T) { 166 _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) 167 if err != nil { 168 t.Fatalf("failed to create pristine chain: %v", err) 169 } 170 defer blockchain.Stop() 171 172 blocks := makeBlockChain(blockchain.CurrentBlock(), 1, ethash.NewFullFaker(), blockchain.db, 0) 173 if _, err := blockchain.InsertChain(blocks); err != nil { 174 t.Fatalf("Failed to insert block: %v", err) 175 } 176 if blocks[len(blocks)-1].Hash() != GetHeadBlockHash(blockchain.db) { 177 t.Fatalf("Write/Get HeadBlockHash failed") 178 } 179 } 180 181 // Tests that given a starting canonical chain of a given size, it can be extended 182 // with various length chains. 183 func TestExtendCanonicalHeaders(t *testing.T) { testExtendCanonical(t, false) } 184 func TestExtendCanonicalBlocks(t *testing.T) { testExtendCanonical(t, true) } 185 186 func testExtendCanonical(t *testing.T, full bool) { 187 length := 5 188 189 // Make first chain starting from genesis 190 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 191 if err != nil { 192 t.Fatalf("failed to make new canonical chain: %v", err) 193 } 194 defer processor.Stop() 195 196 // Define the difficulty comparator 197 better := func(td1, td2 *big.Int) { 198 if td2.Cmp(td1) <= 0 { 199 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 200 } 201 } 202 // Start fork from current height 203 testFork(t, processor, length, 1, full, better) 204 testFork(t, processor, length, 2, full, better) 205 testFork(t, processor, length, 5, full, better) 206 testFork(t, processor, length, 10, full, better) 207 } 208 209 // Tests that given a starting canonical chain of a given size, creating shorter 210 // forks do not take canonical ownership. 211 func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false) } 212 func TestShorterForkBlocks(t *testing.T) { testShorterFork(t, true) } 213 214 func testShorterFork(t *testing.T, full bool) { 215 length := 10 216 217 // Make first chain starting from genesis 218 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 219 if err != nil { 220 t.Fatalf("failed to make new canonical chain: %v", err) 221 } 222 defer processor.Stop() 223 224 // Define the difficulty comparator 225 worse := func(td1, td2 *big.Int) { 226 if td2.Cmp(td1) >= 0 { 227 t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) 228 } 229 } 230 // Sum of numbers must be less than `length` for this to be a shorter fork 231 testFork(t, processor, 0, 3, full, worse) 232 testFork(t, processor, 0, 7, full, worse) 233 testFork(t, processor, 1, 1, full, worse) 234 testFork(t, processor, 1, 7, full, worse) 235 testFork(t, processor, 5, 3, full, worse) 236 testFork(t, processor, 5, 4, full, worse) 237 } 238 239 // Tests that given a starting canonical chain of a given size, creating longer 240 // forks do take canonical ownership. 241 func TestLongerForkHeaders(t *testing.T) { testLongerFork(t, false) } 242 func TestLongerForkBlocks(t *testing.T) { testLongerFork(t, true) } 243 244 func testLongerFork(t *testing.T, full bool) { 245 length := 10 246 247 // Make first chain starting from genesis 248 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 249 if err != nil { 250 t.Fatalf("failed to make new canonical chain: %v", err) 251 } 252 defer processor.Stop() 253 254 // Define the difficulty comparator 255 better := func(td1, td2 *big.Int) { 256 if td2.Cmp(td1) <= 0 { 257 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 258 } 259 } 260 // Sum of numbers must be greater than `length` for this to be a longer fork 261 testFork(t, processor, 0, 11, full, better) 262 testFork(t, processor, 0, 15, full, better) 263 testFork(t, processor, 1, 10, full, better) 264 testFork(t, processor, 1, 12, full, better) 265 testFork(t, processor, 5, 6, full, better) 266 testFork(t, processor, 5, 8, full, better) 267 } 268 269 // Tests that given a starting canonical chain of a given size, creating equal 270 // forks do take canonical ownership. 271 func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false) } 272 func TestEqualForkBlocks(t *testing.T) { testEqualFork(t, true) } 273 274 func testEqualFork(t *testing.T, full bool) { 275 length := 10 276 277 // Make first chain starting from genesis 278 _, processor, err := newCanonical(ethash.NewFaker(), length, full) 279 if err != nil { 280 t.Fatalf("failed to make new canonical chain: %v", err) 281 } 282 defer processor.Stop() 283 284 // Define the difficulty comparator 285 equal := func(td1, td2 *big.Int) { 286 if td2.Cmp(td1) != 0 { 287 t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) 288 } 289 } 290 // Sum of numbers must be equal to `length` for this to be an equal fork 291 testFork(t, processor, 0, 10, full, equal) 292 testFork(t, processor, 1, 9, full, equal) 293 testFork(t, processor, 2, 8, full, equal) 294 testFork(t, processor, 5, 5, full, equal) 295 testFork(t, processor, 6, 4, full, equal) 296 testFork(t, processor, 9, 1, full, equal) 297 } 298 299 // Tests that chains missing links do not get accepted by the processor. 300 func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false) } 301 func TestBrokenBlockChain(t *testing.T) { testBrokenChain(t, true) } 302 303 func testBrokenChain(t *testing.T, full bool) { 304 // Make chain starting from genesis 305 db, blockchain, err := newCanonical(ethash.NewFaker(), 10, full) 306 if err != nil { 307 t.Fatalf("failed to make new canonical chain: %v", err) 308 } 309 defer blockchain.Stop() 310 311 // Create a forked chain, and try to insert with a missing link 312 if full { 313 chain := makeBlockChain(blockchain.CurrentBlock(), 5, ethash.NewFaker(), db, forkSeed)[1:] 314 if err := testBlockChainImport(chain, blockchain); err == nil { 315 t.Errorf("broken block chain not reported") 316 } 317 } else { 318 chain := makeHeaderChain(blockchain.CurrentHeader(), 5, ethash.NewFaker(), db, forkSeed)[1:] 319 if err := testHeaderChainImport(chain, blockchain); err == nil { 320 t.Errorf("broken header chain not reported") 321 } 322 } 323 } 324 325 // Tests that reorganising a long difficult chain after a short easy one 326 // overwrites the canonical numbers and links in the database. 327 func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) } 328 func TestReorgLongBlocks(t *testing.T) { testReorgLong(t, true) } 329 330 func testReorgLong(t *testing.T, full bool) { 331 testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280, full) 332 } 333 334 // Tests that reorganising a short difficult chain after a long easy one 335 // overwrites the canonical numbers and links in the database. 336 func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false) } 337 func TestReorgShortBlocks(t *testing.T) { testReorgShort(t, true) } 338 339 func testReorgShort(t *testing.T, full bool) { 340 // Create a long easy chain vs. a short heavy one. Due to difficulty adjustment 341 // we need a fairly long chain of blocks with different difficulties for a short 342 // one to become heavyer than a long one. The 96 is an empirical value. 343 easy := make([]int64, 96) 344 for i := 0; i < len(easy); i++ { 345 easy[i] = 60 346 } 347 diff := make([]int64, len(easy)-1) 348 for i := 0; i < len(diff); i++ { 349 diff[i] = -9 350 } 351 testReorg(t, easy, diff, 12615120, full) 352 } 353 354 func testReorg(t *testing.T, first, second []int64, td int64, full bool) { 355 // Create a pristine chain and database 356 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 357 if err != nil { 358 t.Fatalf("failed to create pristine chain: %v", err) 359 } 360 defer blockchain.Stop() 361 362 // Insert an easy and a difficult chain afterwards 363 easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db, len(first), func(i int, b *BlockGen) { 364 b.OffsetTime(first[i]) 365 }) 366 diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db, len(second), func(i int, b *BlockGen) { 367 b.OffsetTime(second[i]) 368 }) 369 if full { 370 if _, err := blockchain.InsertChain(easyBlocks); err != nil { 371 t.Fatalf("failed to insert easy chain: %v", err) 372 } 373 if _, err := blockchain.InsertChain(diffBlocks); err != nil { 374 t.Fatalf("failed to insert difficult chain: %v", err) 375 } 376 } else { 377 easyHeaders := make([]*types.Header, len(easyBlocks)) 378 for i, block := range easyBlocks { 379 easyHeaders[i] = block.Header() 380 } 381 diffHeaders := make([]*types.Header, len(diffBlocks)) 382 for i, block := range diffBlocks { 383 diffHeaders[i] = block.Header() 384 } 385 if _, err := blockchain.InsertHeaderChain(easyHeaders, 1); err != nil { 386 t.Fatalf("failed to insert easy chain: %v", err) 387 } 388 if _, err := blockchain.InsertHeaderChain(diffHeaders, 1); err != nil { 389 t.Fatalf("failed to insert difficult chain: %v", err) 390 } 391 } 392 // Check that the chain is valid number and link wise 393 if full { 394 prev := blockchain.CurrentBlock() 395 for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, blockchain.GetBlockByNumber(block.NumberU64()-1) { 396 if prev.ParentHash() != block.Hash() { 397 t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash(), block.Hash()) 398 } 399 } 400 } else { 401 prev := blockchain.CurrentHeader() 402 for header := blockchain.GetHeaderByNumber(blockchain.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, blockchain.GetHeaderByNumber(header.Number.Uint64()-1) { 403 if prev.ParentHash != header.Hash() { 404 t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash()) 405 } 406 } 407 } 408 // Make sure the chain total difficulty is the correct one 409 want := new(big.Int).Add(blockchain.genesisBlock.Difficulty(), big.NewInt(td)) 410 if full { 411 if have := blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()); have.Cmp(want) != 0 { 412 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 413 } 414 } else { 415 if have := blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()); have.Cmp(want) != 0 { 416 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 417 } 418 } 419 } 420 421 // Tests that the insertion functions detect banned hashes. 422 func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) } 423 func TestBadBlockHashes(t *testing.T) { testBadHashes(t, true) } 424 425 func testBadHashes(t *testing.T, full bool) { 426 // Create a pristine chain and database 427 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 428 if err != nil { 429 t.Fatalf("failed to create pristine chain: %v", err) 430 } 431 defer blockchain.Stop() 432 433 // Create a chain, ban a hash and try to import 434 if full { 435 blocks := makeBlockChain(blockchain.CurrentBlock(), 3, ethash.NewFaker(), db, 10) 436 437 BadHashes[blocks[2].Header().Hash()] = true 438 defer func() { delete(BadHashes, blocks[2].Header().Hash()) }() 439 440 _, err = blockchain.InsertChain(blocks) 441 } else { 442 headers := makeHeaderChain(blockchain.CurrentHeader(), 3, ethash.NewFaker(), db, 10) 443 444 BadHashes[headers[2].Hash()] = true 445 defer func() { delete(BadHashes, headers[2].Hash()) }() 446 447 _, err = blockchain.InsertHeaderChain(headers, 1) 448 } 449 if err != ErrBlacklistedHash { 450 t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash) 451 } 452 } 453 454 // Tests that bad hashes are detected on boot, and the chain rolled back to a 455 // good state prior to the bad hash. 456 func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) } 457 func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) } 458 459 func testReorgBadHashes(t *testing.T, full bool) { 460 // Create a pristine chain and database 461 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 462 if err != nil { 463 t.Fatalf("failed to create pristine chain: %v", err) 464 } 465 // Create a chain, import and ban afterwards 466 headers := makeHeaderChain(blockchain.CurrentHeader(), 4, ethash.NewFaker(), db, 10) 467 blocks := makeBlockChain(blockchain.CurrentBlock(), 4, ethash.NewFaker(), db, 10) 468 469 if full { 470 if _, err = blockchain.InsertChain(blocks); err != nil { 471 t.Errorf("failed to import blocks: %v", err) 472 } 473 if blockchain.CurrentBlock().Hash() != blocks[3].Hash() { 474 t.Errorf("last block hash mismatch: have: %x, want %x", blockchain.CurrentBlock().Hash(), blocks[3].Header().Hash()) 475 } 476 BadHashes[blocks[3].Header().Hash()] = true 477 defer func() { delete(BadHashes, blocks[3].Header().Hash()) }() 478 } else { 479 if _, err = blockchain.InsertHeaderChain(headers, 1); err != nil { 480 t.Errorf("failed to import headers: %v", err) 481 } 482 if blockchain.CurrentHeader().Hash() != headers[3].Hash() { 483 t.Errorf("last header hash mismatch: have: %x, want %x", blockchain.CurrentHeader().Hash(), headers[3].Hash()) 484 } 485 BadHashes[headers[3].Hash()] = true 486 defer func() { delete(BadHashes, headers[3].Hash()) }() 487 } 488 blockchain.Stop() 489 490 // Create a new BlockChain and check that it rolled back the state. 491 ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, ethash.NewFaker(), vm.Config{}) 492 if err != nil { 493 t.Fatalf("failed to create new chain manager: %v", err) 494 } 495 if full { 496 if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() { 497 t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash()) 498 } 499 if blocks[2].Header().GasLimit != ncm.GasLimit() { 500 t.Errorf("last block gasLimit mismatch: have: %d, want %d", ncm.GasLimit(), blocks[2].Header().GasLimit) 501 } 502 } else { 503 if ncm.CurrentHeader().Hash() != headers[2].Hash() { 504 t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) 505 } 506 } 507 ncm.Stop() 508 } 509 510 // Tests chain insertions in the face of one entity containing an invalid nonce. 511 func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false) } 512 func TestBlocksInsertNonceError(t *testing.T) { testInsertNonceError(t, true) } 513 514 func testInsertNonceError(t *testing.T, full bool) { 515 for i := 1; i < 25 && !t.Failed(); i++ { 516 // Create a pristine chain and database 517 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full) 518 if err != nil { 519 t.Fatalf("failed to create pristine chain: %v", err) 520 } 521 defer blockchain.Stop() 522 523 // Create and insert a chain with a failing nonce 524 var ( 525 failAt int 526 failRes int 527 failNum uint64 528 ) 529 if full { 530 blocks := makeBlockChain(blockchain.CurrentBlock(), i, ethash.NewFaker(), db, 0) 531 532 failAt = rand.Int() % len(blocks) 533 failNum = blocks[failAt].NumberU64() 534 535 blockchain.engine = ethash.NewFakeFailer(failNum) 536 failRes, err = blockchain.InsertChain(blocks) 537 } else { 538 headers := makeHeaderChain(blockchain.CurrentHeader(), i, ethash.NewFaker(), db, 0) 539 540 failAt = rand.Int() % len(headers) 541 failNum = headers[failAt].Number.Uint64() 542 543 blockchain.engine = ethash.NewFakeFailer(failNum) 544 blockchain.hc.engine = blockchain.engine 545 failRes, err = blockchain.InsertHeaderChain(headers, 1) 546 } 547 // Check that the returned error indicates the failure. 548 if failRes != failAt { 549 t.Errorf("test %d: failure index mismatch: have %d, want %d", i, failRes, failAt) 550 } 551 // Check that all no blocks after the failing block have been inserted. 552 for j := 0; j < i-failAt; j++ { 553 if full { 554 if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil { 555 t.Errorf("test %d: invalid block in chain: %v", i, block) 556 } 557 } else { 558 if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil { 559 t.Errorf("test %d: invalid header in chain: %v", i, header) 560 } 561 } 562 } 563 } 564 } 565 566 // Tests that fast importing a block chain produces the same chain data as the 567 // classical full block processing. 568 func TestFastVsFullChains(t *testing.T) { 569 // Configure and generate a sample block chain 570 var ( 571 gendb, _ = ethdb.NewMemDatabase() 572 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 573 address = crypto.PubkeyToAddress(key.PublicKey) 574 funds = big.NewInt(1000000000) 575 gspec = &Genesis{ 576 Config: params.TestChainConfig, 577 Alloc: GenesisAlloc{address: {Balance: funds}}, 578 } 579 genesis = gspec.MustCommit(gendb) 580 signer = types.NewEIP155Signer(gspec.Config.ChainId) 581 ) 582 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, 1024, func(i int, block *BlockGen) { 583 block.SetCoinbase(common.Address{0x00}) 584 585 // If the block number is multiple of 3, send a few bonus transactions to the miner 586 if i%3 == 2 { 587 for j := 0; j < i%4+1; j++ { 588 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key) 589 if err != nil { 590 panic(err) 591 } 592 block.AddTx(tx) 593 } 594 } 595 // If the block number is a multiple of 5, add a few bonus uncles to the block 596 if i%5 == 5 { 597 block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))}) 598 } 599 }) 600 // Import the chain as an archive node for the comparison baseline 601 archiveDb, _ := ethdb.NewMemDatabase() 602 gspec.MustCommit(archiveDb) 603 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 604 defer archive.Stop() 605 606 if n, err := archive.InsertChain(blocks); err != nil { 607 t.Fatalf("failed to process block %d: %v", n, err) 608 } 609 // Fast import the chain as a non-archive node to test 610 fastDb, _ := ethdb.NewMemDatabase() 611 gspec.MustCommit(fastDb) 612 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 613 defer fast.Stop() 614 615 headers := make([]*types.Header, len(blocks)) 616 for i, block := range blocks { 617 headers[i] = block.Header() 618 } 619 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 620 t.Fatalf("failed to insert header %d: %v", n, err) 621 } 622 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 623 t.Fatalf("failed to insert receipt %d: %v", n, err) 624 } 625 // Iterate over all chain data components, and cross reference 626 for i := 0; i < len(blocks); i++ { 627 num, hash := blocks[i].NumberU64(), blocks[i].Hash() 628 629 if ftd, atd := fast.GetTdByHash(hash), archive.GetTdByHash(hash); ftd.Cmp(atd) != 0 { 630 t.Errorf("block #%d [%x]: td mismatch: have %v, want %v", num, hash, ftd, atd) 631 } 632 if fheader, aheader := fast.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); fheader.Hash() != aheader.Hash() { 633 t.Errorf("block #%d [%x]: header mismatch: have %v, want %v", num, hash, fheader, aheader) 634 } 635 if fblock, ablock := fast.GetBlockByHash(hash), archive.GetBlockByHash(hash); fblock.Hash() != ablock.Hash() { 636 t.Errorf("block #%d [%x]: block mismatch: have %v, want %v", num, hash, fblock, ablock) 637 } else if types.DeriveSha(fblock.Transactions()) != types.DeriveSha(ablock.Transactions()) { 638 t.Errorf("block #%d [%x]: transactions mismatch: have %v, want %v", num, hash, fblock.Transactions(), ablock.Transactions()) 639 } else if types.CalcUncleHash(fblock.Uncles()) != types.CalcUncleHash(ablock.Uncles()) { 640 t.Errorf("block #%d [%x]: uncles mismatch: have %v, want %v", num, hash, fblock.Uncles(), ablock.Uncles()) 641 } 642 if freceipts, areceipts := GetBlockReceipts(fastDb, hash, GetBlockNumber(fastDb, hash)), GetBlockReceipts(archiveDb, hash, GetBlockNumber(archiveDb, hash)); types.DeriveSha(freceipts) != types.DeriveSha(areceipts) { 643 t.Errorf("block #%d [%x]: receipts mismatch: have %v, want %v", num, hash, freceipts, areceipts) 644 } 645 } 646 // Check that the canonical chains are the same between the databases 647 for i := 0; i < len(blocks)+1; i++ { 648 if fhash, ahash := GetCanonicalHash(fastDb, uint64(i)), GetCanonicalHash(archiveDb, uint64(i)); fhash != ahash { 649 t.Errorf("block #%d: canonical hash mismatch: have %v, want %v", i, fhash, ahash) 650 } 651 } 652 } 653 654 // Tests that various import methods move the chain head pointers to the correct 655 // positions. 656 func TestLightVsFastVsFullChainHeads(t *testing.T) { 657 // Configure and generate a sample block chain 658 var ( 659 gendb, _ = ethdb.NewMemDatabase() 660 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 661 address = crypto.PubkeyToAddress(key.PublicKey) 662 funds = big.NewInt(1000000000) 663 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 664 genesis = gspec.MustCommit(gendb) 665 ) 666 height := uint64(1024) 667 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil) 668 669 // Configure a subchain to roll back 670 remove := []common.Hash{} 671 for _, block := range blocks[height/2:] { 672 remove = append(remove, block.Hash()) 673 } 674 // Create a small assertion method to check the three heads 675 assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { 676 if num := chain.CurrentBlock().NumberU64(); num != block { 677 t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) 678 } 679 if num := chain.CurrentFastBlock().NumberU64(); num != fast { 680 t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast) 681 } 682 if num := chain.CurrentHeader().Number.Uint64(); num != header { 683 t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header) 684 } 685 } 686 // Import the chain as an archive node and ensure all pointers are updated 687 archiveDb, _ := ethdb.NewMemDatabase() 688 gspec.MustCommit(archiveDb) 689 690 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 691 if n, err := archive.InsertChain(blocks); err != nil { 692 t.Fatalf("failed to process block %d: %v", n, err) 693 } 694 defer archive.Stop() 695 696 assert(t, "archive", archive, height, height, height) 697 archive.Rollback(remove) 698 assert(t, "archive", archive, height/2, height/2, height/2) 699 700 // Import the chain as a non-archive node and ensure all pointers are updated 701 fastDb, _ := ethdb.NewMemDatabase() 702 gspec.MustCommit(fastDb) 703 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 704 defer fast.Stop() 705 706 headers := make([]*types.Header, len(blocks)) 707 for i, block := range blocks { 708 headers[i] = block.Header() 709 } 710 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 711 t.Fatalf("failed to insert header %d: %v", n, err) 712 } 713 if n, err := fast.InsertReceiptChain(blocks, receipts); err != nil { 714 t.Fatalf("failed to insert receipt %d: %v", n, err) 715 } 716 assert(t, "fast", fast, height, height, 0) 717 fast.Rollback(remove) 718 assert(t, "fast", fast, height/2, height/2, 0) 719 720 // Import the chain as a light node and ensure all pointers are updated 721 lightDb, _ := ethdb.NewMemDatabase() 722 gspec.MustCommit(lightDb) 723 724 light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 725 if n, err := light.InsertHeaderChain(headers, 1); err != nil { 726 t.Fatalf("failed to insert header %d: %v", n, err) 727 } 728 defer light.Stop() 729 730 assert(t, "light", light, height, 0, 0) 731 light.Rollback(remove) 732 assert(t, "light", light, height/2, 0, 0) 733 } 734 735 // Tests that chain reorganisations handle transaction removals and reinsertions. 736 func TestChainTxReorgs(t *testing.T) { 737 var ( 738 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 739 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 740 key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 741 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 742 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 743 addr3 = crypto.PubkeyToAddress(key3.PublicKey) 744 db, _ = ethdb.NewMemDatabase() 745 gspec = &Genesis{ 746 Config: params.TestChainConfig, 747 GasLimit: 3141592, 748 Alloc: GenesisAlloc{ 749 addr1: {Balance: big.NewInt(1000000)}, 750 addr2: {Balance: big.NewInt(1000000)}, 751 addr3: {Balance: big.NewInt(1000000)}, 752 }, 753 } 754 genesis = gspec.MustCommit(db) 755 signer = types.NewEIP155Signer(gspec.Config.ChainId) 756 ) 757 758 // Create two transactions shared between the chains: 759 // - postponed: transaction included at a later block in the forked chain 760 // - swapped: transaction included at the same block number in the forked chain 761 postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 762 swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 763 764 // Create two transactions that will be dropped by the forked chain: 765 // - pastDrop: transaction dropped retroactively from a past block 766 // - freshDrop: transaction dropped exactly at the block where the reorg is detected 767 var pastDrop, freshDrop *types.Transaction 768 769 // Create three transactions that will be added in the forked chain: 770 // - pastAdd: transaction added before the reorganization is detected 771 // - freshAdd: transaction added at the exact block the reorg is detected 772 // - futureAdd: transaction added after the reorg has already finished 773 var pastAdd, freshAdd, futureAdd *types.Transaction 774 775 chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) { 776 switch i { 777 case 0: 778 pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 779 780 gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point 781 gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork 782 783 case 2: 784 freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 785 786 gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point 787 gen.AddTx(swapped) // This transaction will be swapped out at the exact height 788 789 gen.OffsetTime(9) // Lower the block difficulty to simulate a weaker chain 790 } 791 }) 792 // Import the chain. This runs all block validation rules. 793 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 794 if i, err := blockchain.InsertChain(chain); err != nil { 795 t.Fatalf("failed to insert original chain[%d]: %v", i, err) 796 } 797 defer blockchain.Stop() 798 799 // overwrite the old chain 800 chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) { 801 switch i { 802 case 0: 803 pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 804 gen.AddTx(pastAdd) // This transaction needs to be injected during reorg 805 806 case 2: 807 gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain 808 gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain 809 810 freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 811 gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time 812 813 case 3: 814 futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 815 gen.AddTx(futureAdd) // This transaction will be added after a full reorg 816 } 817 }) 818 if _, err := blockchain.InsertChain(chain); err != nil { 819 t.Fatalf("failed to insert forked chain: %v", err) 820 } 821 822 // removed tx 823 for i, tx := range (types.Transactions{pastDrop, freshDrop}) { 824 if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn != nil { 825 t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) 826 } 827 if rcpt, _, _, _ := GetReceipt(db, tx.Hash()); rcpt != nil { 828 t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt) 829 } 830 } 831 // added tx 832 for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) { 833 if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn == nil { 834 t.Errorf("add %d: expected tx to be found", i) 835 } 836 if rcpt, _, _, _ := GetReceipt(db, tx.Hash()); rcpt == nil { 837 t.Errorf("add %d: expected receipt to be found", i) 838 } 839 } 840 // shared tx 841 for i, tx := range (types.Transactions{postponed, swapped}) { 842 if txn, _, _, _ := GetTransaction(db, tx.Hash()); txn == nil { 843 t.Errorf("share %d: expected tx to be found", i) 844 } 845 if rcpt, _, _, _ := GetReceipt(db, tx.Hash()); rcpt == nil { 846 t.Errorf("share %d: expected receipt to be found", i) 847 } 848 } 849 } 850 851 func TestLogReorgs(t *testing.T) { 852 853 var ( 854 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 855 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 856 db, _ = ethdb.NewMemDatabase() 857 // this code generates a log 858 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 859 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 860 genesis = gspec.MustCommit(db) 861 signer = types.NewEIP155Signer(gspec.Config.ChainId) 862 ) 863 864 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 865 defer blockchain.Stop() 866 867 rmLogsCh := make(chan RemovedLogsEvent) 868 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 869 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 870 if i == 1 { 871 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 872 if err != nil { 873 t.Fatalf("failed to create tx: %v", err) 874 } 875 gen.AddTx(tx) 876 } 877 }) 878 if _, err := blockchain.InsertChain(chain); err != nil { 879 t.Fatalf("failed to insert chain: %v", err) 880 } 881 882 chain, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 883 if _, err := blockchain.InsertChain(chain); err != nil { 884 t.Fatalf("failed to insert forked chain: %v", err) 885 } 886 887 timeout := time.NewTimer(1 * time.Second) 888 select { 889 case ev := <-rmLogsCh: 890 if len(ev.Logs) == 0 { 891 t.Error("expected logs") 892 } 893 case <-timeout.C: 894 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 895 } 896 } 897 898 func TestReorgSideEvent(t *testing.T) { 899 var ( 900 db, _ = ethdb.NewMemDatabase() 901 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 902 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 903 gspec = &Genesis{ 904 Config: params.TestChainConfig, 905 Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}, 906 } 907 genesis = gspec.MustCommit(db) 908 signer = types.NewEIP155Signer(gspec.Config.ChainId) 909 ) 910 911 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 912 defer blockchain.Stop() 913 914 chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 915 if _, err := blockchain.InsertChain(chain); err != nil { 916 t.Fatalf("failed to insert chain: %v", err) 917 } 918 919 replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) { 920 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), nil), signer, key1) 921 if i == 2 { 922 gen.OffsetTime(-9) 923 } 924 if err != nil { 925 t.Fatalf("failed to create tx: %v", err) 926 } 927 gen.AddTx(tx) 928 }) 929 chainSideCh := make(chan ChainSideEvent, 64) 930 blockchain.SubscribeChainSideEvent(chainSideCh) 931 if _, err := blockchain.InsertChain(replacementBlocks); err != nil { 932 t.Fatalf("failed to insert chain: %v", err) 933 } 934 935 // first two block of the secondary chain are for a brief moment considered 936 // side chains because up to that point the first one is considered the 937 // heavier chain. 938 expectedSideHashes := map[common.Hash]bool{ 939 replacementBlocks[0].Hash(): true, 940 replacementBlocks[1].Hash(): true, 941 chain[0].Hash(): true, 942 chain[1].Hash(): true, 943 chain[2].Hash(): true, 944 } 945 946 i := 0 947 948 const timeoutDura = 10 * time.Second 949 timeout := time.NewTimer(timeoutDura) 950 done: 951 for { 952 select { 953 case ev := <-chainSideCh: 954 block := ev.Block 955 if _, ok := expectedSideHashes[block.Hash()]; !ok { 956 t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash()) 957 } 958 i++ 959 960 if i == len(expectedSideHashes) { 961 timeout.Stop() 962 963 break done 964 } 965 timeout.Reset(timeoutDura) 966 967 case <-timeout.C: 968 t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent") 969 } 970 } 971 972 // make sure no more events are fired 973 select { 974 case e := <-chainSideCh: 975 t.Errorf("unexpected event fired: %v", e) 976 case <-time.After(250 * time.Millisecond): 977 } 978 979 } 980 981 // Tests if the canonical block can be fetched from the database during chain insertion. 982 func TestCanonicalBlockRetrieval(t *testing.T) { 983 _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true) 984 if err != nil { 985 t.Fatalf("failed to create pristine chain: %v", err) 986 } 987 defer blockchain.Stop() 988 989 chain, _ := GenerateChain(blockchain.chainConfig, blockchain.genesisBlock, ethash.NewFaker(), blockchain.db, 10, func(i int, gen *BlockGen) {}) 990 991 var pend sync.WaitGroup 992 pend.Add(len(chain)) 993 994 for i := range chain { 995 go func(block *types.Block) { 996 defer pend.Done() 997 998 // try to retrieve a block by its canonical hash and see if the block data can be retrieved. 999 for { 1000 ch := GetCanonicalHash(blockchain.db, block.NumberU64()) 1001 if ch == (common.Hash{}) { 1002 continue // busy wait for canonical hash to be written 1003 } 1004 if ch != block.Hash() { 1005 t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex()) 1006 } 1007 fb := GetBlock(blockchain.db, ch, block.NumberU64()) 1008 if fb == nil { 1009 t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex()) 1010 } 1011 if fb.Hash() != block.Hash() { 1012 t.Fatalf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex()) 1013 } 1014 return 1015 } 1016 }(chain[i]) 1017 1018 if _, err := blockchain.InsertChain(types.Blocks{chain[i]}); err != nil { 1019 t.Fatalf("failed to insert block %d: %v", i, err) 1020 } 1021 } 1022 pend.Wait() 1023 } 1024 1025 func TestEIP155Transition(t *testing.T) { 1026 // Configure and generate a sample block chain 1027 var ( 1028 db, _ = ethdb.NewMemDatabase() 1029 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1030 address = crypto.PubkeyToAddress(key.PublicKey) 1031 funds = big.NewInt(1000000000) 1032 deleteAddr = common.Address{1} 1033 gspec = &Genesis{ 1034 Config: ¶ms.ChainConfig{ChainId: big.NewInt(1), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}, 1035 Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, 1036 } 1037 genesis = gspec.MustCommit(db) 1038 ) 1039 1040 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 1041 defer blockchain.Stop() 1042 1043 blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1044 var ( 1045 tx *types.Transaction 1046 err error 1047 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1048 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1049 } 1050 ) 1051 switch i { 1052 case 0: 1053 tx, err = basicTx(types.HomesteadSigner{}) 1054 if err != nil { 1055 t.Fatal(err) 1056 } 1057 block.AddTx(tx) 1058 case 2: 1059 tx, err = basicTx(types.HomesteadSigner{}) 1060 if err != nil { 1061 t.Fatal(err) 1062 } 1063 block.AddTx(tx) 1064 1065 tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainId)) 1066 if err != nil { 1067 t.Fatal(err) 1068 } 1069 block.AddTx(tx) 1070 case 3: 1071 tx, err = basicTx(types.HomesteadSigner{}) 1072 if err != nil { 1073 t.Fatal(err) 1074 } 1075 block.AddTx(tx) 1076 1077 tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainId)) 1078 if err != nil { 1079 t.Fatal(err) 1080 } 1081 block.AddTx(tx) 1082 } 1083 }) 1084 1085 if _, err := blockchain.InsertChain(blocks); err != nil { 1086 t.Fatal(err) 1087 } 1088 block := blockchain.GetBlockByNumber(1) 1089 if block.Transactions()[0].Protected() { 1090 t.Error("Expected block[0].txs[0] to not be replay protected") 1091 } 1092 1093 block = blockchain.GetBlockByNumber(3) 1094 if block.Transactions()[0].Protected() { 1095 t.Error("Expected block[3].txs[0] to not be replay protected") 1096 } 1097 if !block.Transactions()[1].Protected() { 1098 t.Error("Expected block[3].txs[1] to be replay protected") 1099 } 1100 if _, err := blockchain.InsertChain(blocks[4:]); err != nil { 1101 t.Fatal(err) 1102 } 1103 1104 // generate an invalid chain id transaction 1105 config := ¶ms.ChainConfig{ChainId: big.NewInt(2), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)} 1106 blocks, _ = GenerateChain(config, blocks[len(blocks)-1], ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1107 var ( 1108 tx *types.Transaction 1109 err error 1110 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1111 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1112 } 1113 ) 1114 switch i { 1115 case 0: 1116 tx, err = basicTx(types.NewEIP155Signer(big.NewInt(2))) 1117 if err != nil { 1118 t.Fatal(err) 1119 } 1120 block.AddTx(tx) 1121 } 1122 }) 1123 _, err := blockchain.InsertChain(blocks) 1124 if err != types.ErrInvalidChainId { 1125 t.Error("expected error:", types.ErrInvalidChainId) 1126 } 1127 } 1128 1129 func TestEIP161AccountRemoval(t *testing.T) { 1130 // Configure and generate a sample block chain 1131 var ( 1132 db, _ = ethdb.NewMemDatabase() 1133 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1134 address = crypto.PubkeyToAddress(key.PublicKey) 1135 funds = big.NewInt(1000000000) 1136 theAddr = common.Address{1} 1137 gspec = &Genesis{ 1138 Config: ¶ms.ChainConfig{ 1139 ChainId: big.NewInt(1), 1140 HomesteadBlock: new(big.Int), 1141 EIP155Block: new(big.Int), 1142 EIP158Block: big.NewInt(2), 1143 }, 1144 Alloc: GenesisAlloc{address: {Balance: funds}}, 1145 } 1146 genesis = gspec.MustCommit(db) 1147 ) 1148 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) 1149 defer blockchain.Stop() 1150 1151 blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, block *BlockGen) { 1152 var ( 1153 tx *types.Transaction 1154 err error 1155 signer = types.NewEIP155Signer(gspec.Config.ChainId) 1156 ) 1157 switch i { 1158 case 0: 1159 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1160 case 1: 1161 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1162 case 2: 1163 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1164 } 1165 if err != nil { 1166 t.Fatal(err) 1167 } 1168 block.AddTx(tx) 1169 }) 1170 // account must exist pre eip 161 1171 if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { 1172 t.Fatal(err) 1173 } 1174 if st, _ := blockchain.State(); !st.Exist(theAddr) { 1175 t.Error("expected account to exist") 1176 } 1177 1178 // account needs to be deleted post eip 161 1179 if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil { 1180 t.Fatal(err) 1181 } 1182 if st, _ := blockchain.State(); st.Exist(theAddr) { 1183 t.Error("account should not exist") 1184 } 1185 1186 // account musn't be created post eip 161 1187 if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil { 1188 t.Fatal(err) 1189 } 1190 if st, _ := blockchain.State(); st.Exist(theAddr) { 1191 t.Error("account should not exist") 1192 } 1193 } 1194 1195 // This is a regression test (i.e. as weird as it is, don't delete it ever), which 1196 // tests that under weird reorg conditions the blockchain and its internal header- 1197 // chain return the same latest block/header. 1198 // 1199 // https://github.com/ethereum/go-ethereum/pull/15941 1200 func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { 1201 // Generate a canonical chain to act as the main dataset 1202 engine := ethash.NewFaker() 1203 1204 db, _ := ethdb.NewMemDatabase() 1205 genesis := new(Genesis).MustCommit(db) 1206 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1207 1208 // Generate a bunch of fork blocks, each side forking from the canonical chain 1209 forks := make([]*types.Block, len(blocks)) 1210 for i := 0; i < len(forks); i++ { 1211 parent := genesis 1212 if i > 0 { 1213 parent = blocks[i-1] 1214 } 1215 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1216 forks[i] = fork[0] 1217 } 1218 // Import the canonical and fork chain side by side, verifying the current block 1219 // and current header consistency 1220 diskdb, _ := ethdb.NewMemDatabase() 1221 new(Genesis).MustCommit(diskdb) 1222 1223 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) 1224 if err != nil { 1225 t.Fatalf("failed to create tester chain: %v", err) 1226 } 1227 for i := 0; i < len(blocks); i++ { 1228 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1229 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1230 } 1231 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1232 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]) 1233 } 1234 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1235 t.Fatalf(" fork %d: failed to insert into chain: %v", i, err) 1236 } 1237 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1238 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]) 1239 } 1240 } 1241 } 1242 1243 // Tests that importing small side forks doesn't leave junk in the trie database 1244 // cache (which would eventually cause memory issues). 1245 func TestTrieForkGC(t *testing.T) { 1246 // Generate a canonical chain to act as the main dataset 1247 engine := ethash.NewFaker() 1248 1249 db, _ := ethdb.NewMemDatabase() 1250 genesis := new(Genesis).MustCommit(db) 1251 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1252 1253 // Generate a bunch of fork blocks, each side forking from the canonical chain 1254 forks := make([]*types.Block, len(blocks)) 1255 for i := 0; i < len(forks); i++ { 1256 parent := genesis 1257 if i > 0 { 1258 parent = blocks[i-1] 1259 } 1260 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1261 forks[i] = fork[0] 1262 } 1263 // Import the canonical and fork chain side by side, forcing the trie cache to cache both 1264 diskdb, _ := ethdb.NewMemDatabase() 1265 new(Genesis).MustCommit(diskdb) 1266 1267 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) 1268 if err != nil { 1269 t.Fatalf("failed to create tester chain: %v", err) 1270 } 1271 for i := 0; i < len(blocks); i++ { 1272 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1273 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1274 } 1275 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1276 t.Fatalf("fork %d: failed to insert into chain: %v", i, err) 1277 } 1278 } 1279 // Dereference all the recent tries and ensure no past trie is left in 1280 for i := 0; i < triesInMemory; i++ { 1281 chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root(), common.Hash{}) 1282 chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root(), common.Hash{}) 1283 } 1284 if len(chain.stateCache.TrieDB().Nodes()) > 0 { 1285 t.Fatalf("stale tries still alive after garbase collection") 1286 } 1287 } 1288 1289 // Tests that doing large reorgs works even if the state associated with the 1290 // forking point is not available any more. 1291 func TestLargeReorgTrieGC(t *testing.T) { 1292 // Generate the original common chain segment and the two competing forks 1293 engine := ethash.NewFaker() 1294 1295 db, _ := ethdb.NewMemDatabase() 1296 genesis := new(Genesis).MustCommit(db) 1297 1298 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1299 original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1300 competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) 1301 1302 // Import the shared chain and the original canonical one 1303 diskdb, _ := ethdb.NewMemDatabase() 1304 new(Genesis).MustCommit(diskdb) 1305 1306 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) 1307 if err != nil { 1308 t.Fatalf("failed to create tester chain: %v", err) 1309 } 1310 if _, err := chain.InsertChain(shared); err != nil { 1311 t.Fatalf("failed to insert shared chain: %v", err) 1312 } 1313 if _, err := chain.InsertChain(original); err != nil { 1314 t.Fatalf("failed to insert shared chain: %v", err) 1315 } 1316 // Ensure that the state associated with the forking point is pruned away 1317 if node, _ := chain.stateCache.TrieDB().Node(shared[len(shared)-1].Root()); node != nil { 1318 t.Fatalf("common-but-old ancestor still cache") 1319 } 1320 // Import the competitor chain without exceeding the canonical's TD and ensure 1321 // we have not processed any of the blocks (protection against malicious blocks) 1322 if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil { 1323 t.Fatalf("failed to insert competitor chain: %v", err) 1324 } 1325 for i, block := range competitor[:len(competitor)-2] { 1326 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1327 t.Fatalf("competitor %d: low TD chain became processed", i) 1328 } 1329 } 1330 // Import the head of the competitor chain, triggering the reorg and ensure we 1331 // successfully reprocess all the stashed away blocks. 1332 if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil { 1333 t.Fatalf("failed to finalize competitor chain: %v", err) 1334 } 1335 for i, block := range competitor[:len(competitor)-triesInMemory] { 1336 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1337 t.Fatalf("competitor %d: competing chain state missing", i) 1338 } 1339 } 1340 }