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