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