github.com/fff-chain/go-fff@v0.0.0-20220726032732-1c84420b8a99/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 "errors" 21 "fmt" 22 "io/ioutil" 23 "math/big" 24 "math/rand" 25 "os" 26 "sync" 27 "testing" 28 "time" 29 30 "github.com/fff-chain/go-fff/common" 31 "github.com/fff-chain/go-fff/consensus" 32 "github.com/fff-chain/go-fff/consensus/ethash" 33 "github.com/fff-chain/go-fff/core/rawdb" 34 "github.com/fff-chain/go-fff/core/state" 35 "github.com/fff-chain/go-fff/core/types" 36 "github.com/fff-chain/go-fff/core/vm" 37 "github.com/fff-chain/go-fff/crypto" 38 "github.com/fff-chain/go-fff/ethdb" 39 "github.com/fff-chain/go-fff/params" 40 "github.com/fff-chain/go-fff/trie" 41 ) 42 43 // So we can deterministically seed different blockchains 44 var ( 45 canonicalSeed = 1 46 forkSeed1 = 2 47 forkSeed2 = 3 48 49 TestTriesInMemory = 128 50 ) 51 52 // newCanonical creates a chain database, and injects a deterministic canonical 53 // chain. Depending on the full flag, if creates either a full block chain or a 54 // header only chain. 55 func newCanonical(engine consensus.Engine, n int, full, pipeline bool) (ethdb.Database, *BlockChain, error) { 56 var ( 57 db = rawdb.NewMemoryDatabase() 58 genesis = new(Genesis).MustCommit(db) 59 ) 60 61 // Initialize a fresh chain with only a genesis block 62 var ops []BlockChainOption 63 if pipeline { 64 ops = append(ops, EnablePipelineCommit) 65 } 66 blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil, ops...) 67 // Create and inject the requested chain 68 if n == 0 { 69 return db, blockchain, nil 70 } 71 if full { 72 // Full block-chain requested 73 blocks := makeBlockChain(genesis, n, engine, db, canonicalSeed) 74 _, err := blockchain.InsertChain(blocks) 75 return db, blockchain, err 76 } 77 // Header-only chain requested 78 headers := makeHeaderChain(genesis.Header(), n, engine, db, canonicalSeed) 79 _, err := blockchain.InsertHeaderChain(headers, 1) 80 return db, blockchain, err 81 } 82 83 // Test fork of length N starting from block i 84 func testInvalidStateRootBlockImport(t *testing.T, blockchain *BlockChain, i, n int, pipeline bool) { 85 // Copy old chain up to #i into a new db 86 db, blockchain2, err := newCanonical(ethash.NewFaker(), i, true, pipeline) 87 if err != nil { 88 t.Fatal("could not make new canonical in testFork", err) 89 } 90 defer blockchain2.Stop() 91 92 // Assert the chains have the same header/block at #i 93 hash1 := blockchain.GetBlockByNumber(uint64(i)).Hash() 94 hash2 := blockchain2.GetBlockByNumber(uint64(i)).Hash() 95 if hash1 != hash2 { 96 t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) 97 } 98 // Extend the newly created chain 99 blockChainB := makeBlockChain(blockchain2.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed1) 100 for idx, block := range blockChainB { 101 block.SetRoot(common.Hash{0: byte(forkSeed1), 19: byte(idx)}) 102 } 103 previousBlock := blockchain.CurrentBlock() 104 // Sanity check that the forked chain can be imported into the original 105 if _, err := blockchain.InsertChain(blockChainB); err == nil { 106 t.Fatalf("failed to report insert error") 107 } 108 109 time.Sleep(2 * rewindBadBlockInterval) 110 latestBlock := blockchain.CurrentBlock() 111 if latestBlock.Hash() != previousBlock.Hash() || latestBlock.NumberU64() != previousBlock.NumberU64() { 112 t.Fatalf("rewind do not take effect") 113 } 114 db, blockchain3, err := newCanonical(ethash.NewFaker(), i, true, pipeline) 115 if err != nil { 116 t.Fatal("could not make new canonical in testFork", err) 117 } 118 defer blockchain3.Stop() 119 120 blockChainC := makeBlockChain(blockchain3.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed2) 121 122 if _, err := blockchain.InsertChain(blockChainC); err != nil { 123 t.Fatalf("failed to insert forking chain: %v", err) 124 } 125 } 126 127 // Test fork of length N starting from block i 128 func testFork(t *testing.T, blockchain *BlockChain, i, n int, full, pipeline bool, comparator func(td1, td2 *big.Int)) { 129 // Copy old chain up to #i into a new db 130 db, blockchain2, err := newCanonical(ethash.NewFaker(), i, full, pipeline) 131 if err != nil { 132 t.Fatal("could not make new canonical in testFork", err) 133 } 134 defer blockchain2.Stop() 135 136 // Assert the chains have the same header/block at #i 137 var hash1, hash2 common.Hash 138 if full { 139 hash1 = blockchain.GetBlockByNumber(uint64(i)).Hash() 140 hash2 = blockchain2.GetBlockByNumber(uint64(i)).Hash() 141 } else { 142 hash1 = blockchain.GetHeaderByNumber(uint64(i)).Hash() 143 hash2 = blockchain2.GetHeaderByNumber(uint64(i)).Hash() 144 } 145 if hash1 != hash2 { 146 t.Errorf("chain content mismatch at %d: have hash %v, want hash %v", i, hash2, hash1) 147 } 148 // Extend the newly created chain 149 var ( 150 blockChainB []*types.Block 151 headerChainB []*types.Header 152 ) 153 if full { 154 blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed1) 155 if _, err := blockchain2.InsertChain(blockChainB); err != nil { 156 t.Fatalf("failed to insert forking chain: %v", err) 157 } 158 } else { 159 headerChainB = makeHeaderChain(blockchain2.CurrentHeader(), n, ethash.NewFaker(), db, forkSeed1) 160 if _, err := blockchain2.InsertHeaderChain(headerChainB, 1); err != nil { 161 t.Fatalf("failed to insert forking chain: %v", err) 162 } 163 } 164 // Sanity check that the forked chain can be imported into the original 165 var tdPre, tdPost *big.Int 166 167 if full { 168 tdPre = blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()) 169 if err := testBlockChainImport(blockChainB, pipeline, blockchain); err != nil { 170 t.Fatalf("failed to import forked block chain: %v", err) 171 } 172 tdPost = blockchain.GetTdByHash(blockChainB[len(blockChainB)-1].Hash()) 173 } else { 174 tdPre = blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()) 175 if err := testHeaderChainImport(headerChainB, blockchain); err != nil { 176 t.Fatalf("failed to import forked header chain: %v", err) 177 } 178 tdPost = blockchain.GetTdByHash(headerChainB[len(headerChainB)-1].Hash()) 179 } 180 // Compare the total difficulties of the chains 181 comparator(tdPre, tdPost) 182 } 183 184 // testBlockChainImport tries to process a chain of blocks, writing them into 185 // the database if successful. 186 func testBlockChainImport(chain types.Blocks, pipelineCommit bool, blockchain *BlockChain) error { 187 for _, block := range chain { 188 // Try and process the block 189 err := blockchain.engine.VerifyHeader(blockchain, block.Header(), true) 190 if err == nil { 191 err = blockchain.validator.ValidateBody(block) 192 } 193 if err != nil { 194 if err == ErrKnownBlock { 195 continue 196 } 197 return err 198 } 199 statedb, err := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache, nil) 200 if err != nil { 201 return err 202 } 203 statedb.SetExpectedStateRoot(block.Root()) 204 if pipelineCommit { 205 statedb.EnablePipeCommit() 206 } 207 statedb, receipts, _, usedGas, err := blockchain.processor.Process(block, statedb, vm.Config{}) 208 if err != nil { 209 blockchain.reportBlock(block, receipts, err) 210 return err 211 } 212 err = blockchain.validator.ValidateState(block, statedb, receipts, usedGas, pipelineCommit) 213 if err != nil { 214 blockchain.reportBlock(block, receipts, err) 215 return err 216 } 217 blockchain.chainmu.Lock() 218 rawdb.WriteTd(blockchain.db, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash()))) 219 rawdb.WriteBlock(blockchain.db, block) 220 statedb.Finalise(false) 221 statedb.AccountsIntermediateRoot() 222 statedb.Commit(nil) 223 blockchain.chainmu.Unlock() 224 } 225 return nil 226 } 227 228 // testHeaderChainImport tries to process a chain of header, writing them into 229 // the database if successful. 230 func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error { 231 for _, header := range chain { 232 // Try and validate the header 233 if err := blockchain.engine.VerifyHeader(blockchain, header, false); err != nil { 234 return err 235 } 236 // Manually insert the header into the database, but don't reorganise (allows subsequent testing) 237 blockchain.chainmu.Lock() 238 rawdb.WriteTd(blockchain.db, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash))) 239 rawdb.WriteHeader(blockchain.db, header) 240 blockchain.chainmu.Unlock() 241 } 242 return nil 243 } 244 245 func TestBlockImportVerification(t *testing.T) { 246 length := 5 247 248 // Make first chain starting from genesis 249 _, processor, err := newCanonical(ethash.NewFaker(), length, true, true) 250 if err != nil { 251 t.Fatalf("failed to make new canonical chain: %v", err) 252 } 253 defer processor.Stop() 254 // Start fork from current height 255 processor = EnablePipelineCommit(processor) 256 testInvalidStateRootBlockImport(t, processor, length, 10, true) 257 } 258 259 func TestLastBlock(t *testing.T) { 260 _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true, false) 261 if err != nil { 262 t.Fatalf("failed to create pristine chain: %v", err) 263 } 264 defer blockchain.Stop() 265 266 blocks := makeBlockChain(blockchain.CurrentBlock(), 1, ethash.NewFullFaker(), blockchain.db, 0) 267 if _, err := blockchain.InsertChain(blocks); err != nil { 268 t.Fatalf("Failed to insert block: %v", err) 269 } 270 if blocks[len(blocks)-1].Hash() != rawdb.ReadHeadBlockHash(blockchain.db) { 271 t.Fatalf("Write/Get HeadBlockHash failed") 272 } 273 } 274 275 // Tests that given a starting canonical chain of a given size, it can be extended 276 // with various length chains. 277 func TestExtendCanonicalHeaders(t *testing.T) { 278 testExtendCanonical(t, false, false) 279 280 } 281 func TestExtendCanonicalBlocks(t *testing.T) { 282 testExtendCanonical(t, true, false) 283 testExtendCanonical(t, true, true) 284 } 285 286 func testExtendCanonical(t *testing.T, full, pipeline bool) { 287 length := 5 288 289 // Make first chain starting from genesis 290 _, processor, err := newCanonical(ethash.NewFaker(), length, full, pipeline) 291 if err != nil { 292 t.Fatalf("failed to make new canonical chain: %v", err) 293 } 294 defer processor.Stop() 295 296 // Define the difficulty comparator 297 better := func(td1, td2 *big.Int) { 298 if td2.Cmp(td1) <= 0 { 299 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 300 } 301 } 302 // Start fork from current height 303 testFork(t, processor, length, 1, full, pipeline, better) 304 testFork(t, processor, length, 2, full, pipeline, better) 305 testFork(t, processor, length, 5, full, pipeline, better) 306 testFork(t, processor, length, 10, full, pipeline, better) 307 } 308 309 // Tests that given a starting canonical chain of a given size, creating shorter 310 // forks do not take canonical ownership. 311 func TestShorterForkHeaders(t *testing.T) { testShorterFork(t, false, false) } 312 func TestShorterForkBlocks(t *testing.T) { 313 testShorterFork(t, true, false) 314 testShorterFork(t, true, true) 315 } 316 317 func testShorterFork(t *testing.T, full, pipeline bool) { 318 length := 10 319 320 // Make first chain starting from genesis 321 _, processor, err := newCanonical(ethash.NewFaker(), length, full, pipeline) 322 if err != nil { 323 t.Fatalf("failed to make new canonical chain: %v", err) 324 } 325 defer processor.Stop() 326 327 // Define the difficulty comparator 328 worse := func(td1, td2 *big.Int) { 329 if td2.Cmp(td1) >= 0 { 330 t.Errorf("total difficulty mismatch: have %v, expected less than %v", td2, td1) 331 } 332 } 333 // Sum of numbers must be less than `length` for this to be a shorter fork 334 testFork(t, processor, 0, 3, full, pipeline, worse) 335 testFork(t, processor, 0, 7, full, pipeline, worse) 336 testFork(t, processor, 1, 1, full, pipeline, worse) 337 testFork(t, processor, 1, 7, full, pipeline, worse) 338 testFork(t, processor, 5, 3, full, pipeline, worse) 339 testFork(t, processor, 5, 4, full, pipeline, worse) 340 } 341 342 // Tests that given a starting canonical chain of a given size, creating longer 343 // forks do take canonical ownership. 344 func TestLongerForkHeaders(t *testing.T) { 345 testLongerFork(t, false, false) 346 } 347 func TestLongerForkBlocks(t *testing.T) { 348 testLongerFork(t, true, false) 349 testLongerFork(t, true, true) 350 351 } 352 353 func testLongerFork(t *testing.T, full, pipeline bool) { 354 length := 10 355 356 // Make first chain starting from genesis 357 _, processor, err := newCanonical(ethash.NewFaker(), length, full, pipeline) 358 if err != nil { 359 t.Fatalf("failed to make new canonical chain: %v", err) 360 } 361 defer processor.Stop() 362 363 // Define the difficulty comparator 364 better := func(td1, td2 *big.Int) { 365 if td2.Cmp(td1) <= 0 { 366 t.Errorf("total difficulty mismatch: have %v, expected more than %v", td2, td1) 367 } 368 } 369 // Sum of numbers must be greater than `length` for this to be a longer fork 370 testFork(t, processor, 0, 11, full, pipeline, better) 371 testFork(t, processor, 0, 15, full, pipeline, better) 372 testFork(t, processor, 1, 10, full, pipeline, better) 373 testFork(t, processor, 1, 12, full, pipeline, better) 374 testFork(t, processor, 5, 6, full, pipeline, better) 375 testFork(t, processor, 5, 8, full, pipeline, better) 376 } 377 378 // Tests that given a starting canonical chain of a given size, creating equal 379 // forks do take canonical ownership. 380 func TestEqualForkHeaders(t *testing.T) { testEqualFork(t, false, false) } 381 func TestEqualForkBlocks(t *testing.T) { 382 testEqualFork(t, true, true) 383 testEqualFork(t, true, false) 384 385 } 386 387 func testEqualFork(t *testing.T, full, pipeline bool) { 388 length := 10 389 390 // Make first chain starting from genesis 391 _, processor, err := newCanonical(ethash.NewFaker(), length, full, pipeline) 392 if err != nil { 393 t.Fatalf("failed to make new canonical chain: %v", err) 394 } 395 defer processor.Stop() 396 397 // Define the difficulty comparator 398 equal := func(td1, td2 *big.Int) { 399 if td2.Cmp(td1) != 0 { 400 t.Errorf("total difficulty mismatch: have %v, want %v", td2, td1) 401 } 402 } 403 // Sum of numbers must be equal to `length` for this to be an equal fork 404 testFork(t, processor, 0, 10, full, pipeline, equal) 405 testFork(t, processor, 1, 9, full, pipeline, equal) 406 testFork(t, processor, 2, 8, full, pipeline, equal) 407 testFork(t, processor, 5, 5, full, pipeline, equal) 408 testFork(t, processor, 6, 4, full, pipeline, equal) 409 testFork(t, processor, 9, 1, full, pipeline, equal) 410 } 411 412 // Tests that chains missing links do not get accepted by the processor. 413 func TestBrokenHeaderChain(t *testing.T) { testBrokenChain(t, false, false) } 414 func TestBrokenBlockChain(t *testing.T) { 415 testBrokenChain(t, true, false) 416 testBrokenChain(t, true, true) 417 } 418 419 func testBrokenChain(t *testing.T, full, pipeline bool) { 420 // Make chain starting from genesis 421 db, blockchain, err := newCanonical(ethash.NewFaker(), 10, full, pipeline) 422 if err != nil { 423 t.Fatalf("failed to make new canonical chain: %v", err) 424 } 425 defer blockchain.Stop() 426 427 // Create a forked chain, and try to insert with a missing link 428 if full { 429 chain := makeBlockChain(blockchain.CurrentBlock(), 5, ethash.NewFaker(), db, forkSeed1)[1:] 430 if err := testBlockChainImport(chain, pipeline, blockchain); err == nil { 431 t.Errorf("broken block chain not reported") 432 } 433 } else { 434 chain := makeHeaderChain(blockchain.CurrentHeader(), 5, ethash.NewFaker(), db, forkSeed1)[1:] 435 if err := testHeaderChainImport(chain, blockchain); err == nil { 436 t.Errorf("broken header chain not reported") 437 } 438 } 439 } 440 441 // Tests that reorganising a long difficult chain after a short easy one 442 // overwrites the canonical numbers and links in the database. 443 func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false, false) } 444 func TestReorgLongBlocks(t *testing.T) { 445 testReorgLong(t, true, false) 446 testReorgLong(t, true, true) 447 } 448 449 func testReorgLong(t *testing.T, full, pipeline bool) { 450 testReorg(t, []int64{0, 0, -9}, []int64{0, 0, 0, -9}, 393280, full, pipeline) 451 } 452 453 // Tests that reorganising a short difficult chain after a long easy one 454 // overwrites the canonical numbers and links in the database. 455 func TestReorgShortHeaders(t *testing.T) { testReorgShort(t, false, false) } 456 func TestReorgShortBlocks(t *testing.T) { 457 testReorgShort(t, true, false) 458 testReorgShort(t, true, true) 459 } 460 461 func testReorgShort(t *testing.T, full, pipeline bool) { 462 // Create a long easy chain vs. a short heavy one. Due to difficulty adjustment 463 // we need a fairly long chain of blocks with different difficulties for a short 464 // one to become heavyer than a long one. The 96 is an empirical value. 465 easy := make([]int64, 96) 466 for i := 0; i < len(easy); i++ { 467 easy[i] = 60 468 } 469 diff := make([]int64, len(easy)-1) 470 for i := 0; i < len(diff); i++ { 471 diff[i] = -9 472 } 473 testReorg(t, easy, diff, 12615120, full, pipeline) 474 } 475 476 func testReorg(t *testing.T, first, second []int64, td int64, full, pipeline bool) { 477 // Create a pristine chain and database 478 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, pipeline) 479 if err != nil { 480 t.Fatalf("failed to create pristine chain: %v", err) 481 } 482 defer blockchain.Stop() 483 484 // Insert an easy and a difficult chain afterwards 485 easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db, len(first), func(i int, b *BlockGen) { 486 b.OffsetTime(first[i]) 487 }) 488 diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db, len(second), func(i int, b *BlockGen) { 489 b.OffsetTime(second[i]) 490 }) 491 if full { 492 if _, err := blockchain.InsertChain(easyBlocks); err != nil { 493 t.Fatalf("failed to insert easy chain: %v", err) 494 } 495 if _, err := blockchain.InsertChain(diffBlocks); err != nil { 496 t.Fatalf("failed to insert difficult chain: %v", err) 497 } 498 } else { 499 easyHeaders := make([]*types.Header, len(easyBlocks)) 500 for i, block := range easyBlocks { 501 easyHeaders[i] = block.Header() 502 } 503 diffHeaders := make([]*types.Header, len(diffBlocks)) 504 for i, block := range diffBlocks { 505 diffHeaders[i] = block.Header() 506 } 507 if _, err := blockchain.InsertHeaderChain(easyHeaders, 1); err != nil { 508 t.Fatalf("failed to insert easy chain: %v", err) 509 } 510 if _, err := blockchain.InsertHeaderChain(diffHeaders, 1); err != nil { 511 t.Fatalf("failed to insert difficult chain: %v", err) 512 } 513 } 514 // Check that the chain is valid number and link wise 515 if full { 516 prev := blockchain.CurrentBlock() 517 for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, blockchain.GetBlockByNumber(block.NumberU64()-1) { 518 if prev.ParentHash() != block.Hash() { 519 t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash(), block.Hash()) 520 } 521 } 522 } else { 523 prev := blockchain.CurrentHeader() 524 for header := blockchain.GetHeaderByNumber(blockchain.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, blockchain.GetHeaderByNumber(header.Number.Uint64()-1) { 525 if prev.ParentHash != header.Hash() { 526 t.Errorf("parent header hash mismatch: have %x, want %x", prev.ParentHash, header.Hash()) 527 } 528 } 529 } 530 // Make sure the chain total difficulty is the correct one 531 want := new(big.Int).Add(blockchain.genesisBlock.Difficulty(), big.NewInt(td)) 532 if full { 533 if have := blockchain.GetTdByHash(blockchain.CurrentBlock().Hash()); have.Cmp(want) != 0 { 534 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 535 } 536 } else { 537 if have := blockchain.GetTdByHash(blockchain.CurrentHeader().Hash()); have.Cmp(want) != 0 { 538 t.Errorf("total difficulty mismatch: have %v, want %v", have, want) 539 } 540 } 541 } 542 543 // Tests that the insertion functions detect banned hashes. 544 func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false, false) } 545 func TestBadBlockHashes(t *testing.T) { 546 testBadHashes(t, true, true) 547 testBadHashes(t, true, false) 548 549 } 550 551 func testBadHashes(t *testing.T, full, pipeline bool) { 552 // Create a pristine chain and database 553 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, pipeline) 554 if err != nil { 555 t.Fatalf("failed to create pristine chain: %v", err) 556 } 557 defer blockchain.Stop() 558 559 // Create a chain, ban a hash and try to import 560 if full { 561 blocks := makeBlockChain(blockchain.CurrentBlock(), 3, ethash.NewFaker(), db, 10) 562 563 BadHashes[blocks[2].Header().Hash()] = true 564 defer func() { delete(BadHashes, blocks[2].Header().Hash()) }() 565 566 _, err = blockchain.InsertChain(blocks) 567 } else { 568 headers := makeHeaderChain(blockchain.CurrentHeader(), 3, ethash.NewFaker(), db, 10) 569 570 BadHashes[headers[2].Hash()] = true 571 defer func() { delete(BadHashes, headers[2].Hash()) }() 572 573 _, err = blockchain.InsertHeaderChain(headers, 1) 574 } 575 if !errors.Is(err, ErrBlacklistedHash) { 576 t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash) 577 } 578 } 579 580 // Tests that bad hashes are detected on boot, and the chain rolled back to a 581 // good state prior to the bad hash. 582 func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false, false) } 583 func TestReorgBadBlockHashes(t *testing.T) { 584 testReorgBadHashes(t, true, false) 585 testReorgBadHashes(t, true, true) 586 587 } 588 589 func testReorgBadHashes(t *testing.T, full, pipeline bool) { 590 // Create a pristine chain and database 591 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, pipeline) 592 if err != nil { 593 t.Fatalf("failed to create pristine chain: %v", err) 594 } 595 // Create a chain, import and ban afterwards 596 headers := makeHeaderChain(blockchain.CurrentHeader(), 4, ethash.NewFaker(), db, 10) 597 blocks := makeBlockChain(blockchain.CurrentBlock(), 4, ethash.NewFaker(), db, 10) 598 599 if full { 600 if _, err = blockchain.InsertChain(blocks); err != nil { 601 t.Errorf("failed to import blocks: %v", err) 602 } 603 if blockchain.CurrentBlock().Hash() != blocks[3].Hash() { 604 t.Errorf("last block hash mismatch: have: %x, want %x", blockchain.CurrentBlock().Hash(), blocks[3].Header().Hash()) 605 } 606 BadHashes[blocks[3].Header().Hash()] = true 607 defer func() { delete(BadHashes, blocks[3].Header().Hash()) }() 608 } else { 609 if _, err = blockchain.InsertHeaderChain(headers, 1); err != nil { 610 t.Errorf("failed to import headers: %v", err) 611 } 612 if blockchain.CurrentHeader().Hash() != headers[3].Hash() { 613 t.Errorf("last header hash mismatch: have: %x, want %x", blockchain.CurrentHeader().Hash(), headers[3].Hash()) 614 } 615 BadHashes[headers[3].Hash()] = true 616 defer func() { delete(BadHashes, headers[3].Hash()) }() 617 } 618 blockchain.Stop() 619 620 // Create a new BlockChain and check that it rolled back the state. 621 ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, ethash.NewFaker(), vm.Config{}, nil, nil) 622 if err != nil { 623 t.Fatalf("failed to create new chain manager: %v", err) 624 } 625 if full { 626 if ncm.CurrentBlock().Hash() != blocks[2].Header().Hash() { 627 t.Errorf("last block hash mismatch: have: %x, want %x", ncm.CurrentBlock().Hash(), blocks[2].Header().Hash()) 628 } 629 if blocks[2].Header().GasLimit != ncm.GasLimit() { 630 t.Errorf("last block gasLimit mismatch: have: %d, want %d", ncm.GasLimit(), blocks[2].Header().GasLimit) 631 } 632 } else { 633 if ncm.CurrentHeader().Hash() != headers[2].Hash() { 634 t.Errorf("last header hash mismatch: have: %x, want %x", ncm.CurrentHeader().Hash(), headers[2].Hash()) 635 } 636 } 637 ncm.Stop() 638 } 639 640 // Tests chain insertions in the face of one entity containing an invalid nonce. 641 func TestHeadersInsertNonceError(t *testing.T) { testInsertNonceError(t, false, false) } 642 func TestBlocksInsertNonceError(t *testing.T) { 643 testInsertNonceError(t, true, false) 644 testInsertNonceError(t, true, true) 645 } 646 647 func testInsertNonceError(t *testing.T, full, pipeline bool) { 648 for i := 1; i < 25 && !t.Failed(); i++ { 649 // Create a pristine chain and database 650 db, blockchain, err := newCanonical(ethash.NewFaker(), 0, full, pipeline) 651 if err != nil { 652 t.Fatalf("failed to create pristine chain: %v", err) 653 } 654 defer blockchain.Stop() 655 656 // Create and insert a chain with a failing nonce 657 var ( 658 failAt int 659 failRes int 660 failNum uint64 661 ) 662 if full { 663 blocks := makeBlockChain(blockchain.CurrentBlock(), i, ethash.NewFaker(), db, 0) 664 665 failAt = rand.Int() % len(blocks) 666 failNum = blocks[failAt].NumberU64() 667 668 blockchain.engine = ethash.NewFakeFailer(failNum) 669 failRes, err = blockchain.InsertChain(blocks) 670 } else { 671 headers := makeHeaderChain(blockchain.CurrentHeader(), i, ethash.NewFaker(), db, 0) 672 673 failAt = rand.Int() % len(headers) 674 failNum = headers[failAt].Number.Uint64() 675 676 blockchain.engine = ethash.NewFakeFailer(failNum) 677 blockchain.hc.engine = blockchain.engine 678 failRes, err = blockchain.InsertHeaderChain(headers, 1) 679 } 680 // Check that the returned error indicates the failure 681 if failRes != failAt { 682 t.Errorf("test %d: failure (%v) index mismatch: have %d, want %d", i, err, failRes, failAt) 683 } 684 // Check that all blocks after the failing block have been inserted 685 for j := 0; j < i-failAt; j++ { 686 if full { 687 if block := blockchain.GetBlockByNumber(failNum + uint64(j)); block != nil { 688 t.Errorf("test %d: invalid block in chain: %v", i, block) 689 } 690 } else { 691 if header := blockchain.GetHeaderByNumber(failNum + uint64(j)); header != nil { 692 t.Errorf("test %d: invalid header in chain: %v", i, header) 693 } 694 } 695 } 696 } 697 } 698 699 // Tests that fast importing a block chain produces the same chain data as the 700 // classical full block processing. 701 func TestFastVsFullChains(t *testing.T) { 702 // Configure and generate a sample block chain 703 var ( 704 gendb = rawdb.NewMemoryDatabase() 705 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 706 address = crypto.PubkeyToAddress(key.PublicKey) 707 funds = big.NewInt(1000000000) 708 gspec = &Genesis{ 709 Config: params.TestChainConfig, 710 Alloc: GenesisAlloc{address: {Balance: funds}}, 711 } 712 genesis = gspec.MustCommit(gendb) 713 signer = types.LatestSigner(gspec.Config) 714 ) 715 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, 1024, func(i int, block *BlockGen) { 716 block.SetCoinbase(common.Address{0x00}) 717 718 // If the block number is multiple of 3, send a few bonus transactions to the miner 719 if i%3 == 2 { 720 for j := 0; j < i%4+1; j++ { 721 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key) 722 if err != nil { 723 panic(err) 724 } 725 block.AddTx(tx) 726 } 727 } 728 // If the block number is a multiple of 5, add a few bonus uncles to the block 729 if i%5 == 5 { 730 block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))}) 731 } 732 }) 733 // Import the chain as an archive node for the comparison baseline 734 archiveDb := rawdb.NewMemoryDatabase() 735 gspec.MustCommit(archiveDb) 736 archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 737 defer archive.Stop() 738 739 if n, err := archive.InsertChain(blocks); err != nil { 740 t.Fatalf("failed to process block %d: %v", n, err) 741 } 742 // Fast import the chain as a non-archive node to test 743 fastDb := rawdb.NewMemoryDatabase() 744 gspec.MustCommit(fastDb) 745 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 746 defer fast.Stop() 747 748 headers := make([]*types.Header, len(blocks)) 749 for i, block := range blocks { 750 headers[i] = block.Header() 751 } 752 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 753 t.Fatalf("failed to insert header %d: %v", n, err) 754 } 755 if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil { 756 t.Fatalf("failed to insert receipt %d: %v", n, err) 757 } 758 // Freezer style fast import the chain. 759 frdir, err := ioutil.TempDir("", "") 760 if err != nil { 761 t.Fatalf("failed to create temp freezer dir: %v", err) 762 } 763 defer os.Remove(frdir) 764 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false) 765 if err != nil { 766 t.Fatalf("failed to create temp freezer db: %v", err) 767 } 768 gspec.MustCommit(ancientDb) 769 ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 770 defer ancient.Stop() 771 772 if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { 773 t.Fatalf("failed to insert header %d: %v", n, err) 774 } 775 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(len(blocks)/2)); err != nil { 776 t.Fatalf("failed to insert receipt %d: %v", n, err) 777 } 778 // Iterate over all chain data components, and cross reference 779 for i := 0; i < len(blocks); i++ { 780 num, hash := blocks[i].NumberU64(), blocks[i].Hash() 781 782 if ftd, atd := fast.GetTdByHash(hash), archive.GetTdByHash(hash); ftd.Cmp(atd) != 0 { 783 t.Errorf("block #%d [%x]: td mismatch: fastdb %v, archivedb %v", num, hash, ftd, atd) 784 } 785 if antd, artd := ancient.GetTdByHash(hash), archive.GetTdByHash(hash); antd.Cmp(artd) != 0 { 786 t.Errorf("block #%d [%x]: td mismatch: ancientdb %v, archivedb %v", num, hash, antd, artd) 787 } 788 if fheader, aheader := fast.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); fheader.Hash() != aheader.Hash() { 789 t.Errorf("block #%d [%x]: header mismatch: fastdb %v, archivedb %v", num, hash, fheader, aheader) 790 } 791 if anheader, arheader := ancient.GetHeaderByHash(hash), archive.GetHeaderByHash(hash); anheader.Hash() != arheader.Hash() { 792 t.Errorf("block #%d [%x]: header mismatch: ancientdb %v, archivedb %v", num, hash, anheader, arheader) 793 } 794 if fblock, arblock, anblock := fast.GetBlockByHash(hash), archive.GetBlockByHash(hash), ancient.GetBlockByHash(hash); fblock.Hash() != arblock.Hash() || anblock.Hash() != arblock.Hash() { 795 t.Errorf("block #%d [%x]: block mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, fblock, anblock, arblock) 796 } else if types.DeriveSha(fblock.Transactions(), trie.NewStackTrie(nil)) != types.DeriveSha(arblock.Transactions(), trie.NewStackTrie(nil)) || types.DeriveSha(anblock.Transactions(), trie.NewStackTrie(nil)) != types.DeriveSha(arblock.Transactions(), trie.NewStackTrie(nil)) { 797 t.Errorf("block #%d [%x]: transactions mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, fblock.Transactions(), anblock.Transactions(), arblock.Transactions()) 798 } else if types.CalcUncleHash(fblock.Uncles()) != types.CalcUncleHash(arblock.Uncles()) || types.CalcUncleHash(anblock.Uncles()) != types.CalcUncleHash(arblock.Uncles()) { 799 t.Errorf("block #%d [%x]: uncles mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, fblock.Uncles(), anblock, arblock.Uncles()) 800 } 801 if freceipts, anreceipts, areceipts := rawdb.ReadReceipts(fastDb, hash, *rawdb.ReadHeaderNumber(fastDb, hash), fast.Config()), rawdb.ReadReceipts(ancientDb, hash, *rawdb.ReadHeaderNumber(ancientDb, hash), fast.Config()), rawdb.ReadReceipts(archiveDb, hash, *rawdb.ReadHeaderNumber(archiveDb, hash), fast.Config()); types.DeriveSha(freceipts, trie.NewStackTrie(nil)) != types.DeriveSha(areceipts, trie.NewStackTrie(nil)) { 802 t.Errorf("block #%d [%x]: receipts mismatch: fastdb %v, ancientdb %v, archivedb %v", num, hash, freceipts, anreceipts, areceipts) 803 } 804 } 805 // Check that the canonical chains are the same between the databases 806 for i := 0; i < len(blocks)+1; i++ { 807 if fhash, ahash := rawdb.ReadCanonicalHash(fastDb, uint64(i)), rawdb.ReadCanonicalHash(archiveDb, uint64(i)); fhash != ahash { 808 t.Errorf("block #%d: canonical hash mismatch: fastdb %v, archivedb %v", i, fhash, ahash) 809 } 810 if anhash, arhash := rawdb.ReadCanonicalHash(ancientDb, uint64(i)), rawdb.ReadCanonicalHash(archiveDb, uint64(i)); anhash != arhash { 811 t.Errorf("block #%d: canonical hash mismatch: ancientdb %v, archivedb %v", i, anhash, arhash) 812 } 813 } 814 } 815 816 // Tests that various import methods move the chain head pointers to the correct 817 // positions. 818 func TestLightVsFastVsFullChainHeads(t *testing.T) { 819 // Configure and generate a sample block chain 820 var ( 821 gendb = rawdb.NewMemoryDatabase() 822 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 823 address = crypto.PubkeyToAddress(key.PublicKey) 824 funds = big.NewInt(1000000000) 825 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 826 genesis = gspec.MustCommit(gendb) 827 ) 828 height := uint64(1024) 829 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil) 830 831 // makeDb creates a db instance for testing. 832 makeDb := func() (ethdb.Database, func()) { 833 dir, err := ioutil.TempDir("", "") 834 if err != nil { 835 t.Fatalf("failed to create temp freezer dir: %v", err) 836 } 837 defer os.Remove(dir) 838 db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), dir, "", false, false, false) 839 if err != nil { 840 t.Fatalf("failed to create temp freezer db: %v", err) 841 } 842 gspec.MustCommit(db) 843 return db, func() { os.RemoveAll(dir) } 844 } 845 // Configure a subchain to roll back 846 remove := blocks[height/2].NumberU64() 847 848 // Create a small assertion method to check the three heads 849 assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { 850 t.Helper() 851 852 if num := chain.CurrentBlock().NumberU64(); num != block { 853 t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) 854 } 855 if num := chain.CurrentFastBlock().NumberU64(); num != fast { 856 t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast) 857 } 858 if num := chain.CurrentHeader().Number.Uint64(); num != header { 859 t.Errorf("%s head header mismatch: have #%v, want #%v", kind, num, header) 860 } 861 } 862 // Import the chain as an archive node and ensure all pointers are updated 863 archiveDb, delfn := makeDb() 864 defer delfn() 865 866 archiveCaching := *defaultCacheConfig 867 archiveCaching.TrieDirtyDisabled = true 868 869 archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 870 if n, err := archive.InsertChain(blocks); err != nil { 871 t.Fatalf("failed to process block %d: %v", n, err) 872 } 873 defer archive.Stop() 874 875 assert(t, "archive", archive, height, height, height) 876 archive.SetHead(remove - 1) 877 assert(t, "archive", archive, height/2, height/2, height/2) 878 879 // Import the chain as a non-archive node and ensure all pointers are updated 880 fastDb, delfn := makeDb() 881 defer delfn() 882 fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 883 defer fast.Stop() 884 885 headers := make([]*types.Header, len(blocks)) 886 for i, block := range blocks { 887 headers[i] = block.Header() 888 } 889 if n, err := fast.InsertHeaderChain(headers, 1); err != nil { 890 t.Fatalf("failed to insert header %d: %v", n, err) 891 } 892 if n, err := fast.InsertReceiptChain(blocks, receipts, 0); err != nil { 893 t.Fatalf("failed to insert receipt %d: %v", n, err) 894 } 895 assert(t, "fast", fast, height, height, 0) 896 fast.SetHead(remove - 1) 897 assert(t, "fast", fast, height/2, height/2, 0) 898 899 // Import the chain as a ancient-first node and ensure all pointers are updated 900 ancientDb, delfn := makeDb() 901 defer delfn() 902 ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 903 defer ancient.Stop() 904 905 if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { 906 t.Fatalf("failed to insert header %d: %v", n, err) 907 } 908 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { 909 t.Fatalf("failed to insert receipt %d: %v", n, err) 910 } 911 assert(t, "ancient", ancient, height, height, 0) 912 ancient.SetHead(remove - 1) 913 assert(t, "ancient", ancient, 0, 0, 0) 914 915 if frozen, err := ancientDb.Ancients(); err != nil || frozen != 1 { 916 t.Fatalf("failed to truncate ancient store, want %v, have %v", 1, frozen) 917 } 918 // Import the chain as a light node and ensure all pointers are updated 919 lightDb, delfn := makeDb() 920 defer delfn() 921 light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 922 if n, err := light.InsertHeaderChain(headers, 1); err != nil { 923 t.Fatalf("failed to insert header %d: %v", n, err) 924 } 925 defer light.Stop() 926 927 assert(t, "light", light, height, 0, 0) 928 light.SetHead(remove - 1) 929 assert(t, "light", light, height/2, 0, 0) 930 } 931 932 // Tests that chain reorganisations handle transaction removals and reinsertions. 933 func TestChainTxReorgs(t *testing.T) { 934 var ( 935 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 936 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 937 key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 938 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 939 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 940 addr3 = crypto.PubkeyToAddress(key3.PublicKey) 941 db = rawdb.NewMemoryDatabase() 942 gspec = &Genesis{ 943 Config: params.TestChainConfig, 944 GasLimit: 3141592, 945 Alloc: GenesisAlloc{ 946 addr1: {Balance: big.NewInt(1000000)}, 947 addr2: {Balance: big.NewInt(1000000)}, 948 addr3: {Balance: big.NewInt(1000000)}, 949 }, 950 } 951 genesis = gspec.MustCommit(db) 952 signer = types.LatestSigner(gspec.Config) 953 ) 954 955 // Create two transactions shared between the chains: 956 // - postponed: transaction included at a later block in the forked chain 957 // - swapped: transaction included at the same block number in the forked chain 958 postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 959 swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1) 960 961 // Create two transactions that will be dropped by the forked chain: 962 // - pastDrop: transaction dropped retroactively from a past block 963 // - freshDrop: transaction dropped exactly at the block where the reorg is detected 964 var pastDrop, freshDrop *types.Transaction 965 966 // Create three transactions that will be added in the forked chain: 967 // - pastAdd: transaction added before the reorganization is detected 968 // - freshAdd: transaction added at the exact block the reorg is detected 969 // - futureAdd: transaction added after the reorg has already finished 970 var pastAdd, freshAdd, futureAdd *types.Transaction 971 972 chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) { 973 switch i { 974 case 0: 975 pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 976 977 gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point 978 gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork 979 980 case 2: 981 freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2) 982 983 gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point 984 gen.AddTx(swapped) // This transaction will be swapped out at the exact height 985 986 gen.OffsetTime(9) // Lower the block difficulty to simulate a weaker chain 987 } 988 }) 989 // Import the chain. This runs all block validation rules. 990 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 991 if i, err := blockchain.InsertChain(chain); err != nil { 992 t.Fatalf("failed to insert original chain[%d]: %v", i, err) 993 } 994 defer blockchain.Stop() 995 996 // overwrite the old chain 997 chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 5, func(i int, gen *BlockGen) { 998 switch i { 999 case 0: 1000 pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 1001 gen.AddTx(pastAdd) // This transaction needs to be injected during reorg 1002 1003 case 2: 1004 gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain 1005 gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain 1006 1007 freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 1008 gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time 1009 1010 case 3: 1011 futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3) 1012 gen.AddTx(futureAdd) // This transaction will be added after a full reorg 1013 } 1014 }) 1015 if _, err := blockchain.InsertChain(chain); err != nil { 1016 t.Fatalf("failed to insert forked chain: %v", err) 1017 } 1018 1019 // removed tx 1020 for i, tx := range (types.Transactions{pastDrop, freshDrop}) { 1021 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn != nil { 1022 t.Errorf("drop %d: tx %v found while shouldn't have been", i, txn) 1023 } 1024 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt != nil { 1025 t.Errorf("drop %d: receipt %v found while shouldn't have been", i, rcpt) 1026 } 1027 } 1028 // added tx 1029 for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) { 1030 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 1031 t.Errorf("add %d: expected tx to be found", i) 1032 } 1033 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt == nil { 1034 t.Errorf("add %d: expected receipt to be found", i) 1035 } 1036 } 1037 // shared tx 1038 for i, tx := range (types.Transactions{postponed, swapped}) { 1039 if txn, _, _, _ := rawdb.ReadTransaction(db, tx.Hash()); txn == nil { 1040 t.Errorf("share %d: expected tx to be found", i) 1041 } 1042 if rcpt, _, _, _ := rawdb.ReadReceipt(db, tx.Hash(), blockchain.Config()); rcpt == nil { 1043 t.Errorf("share %d: expected receipt to be found", i) 1044 } 1045 } 1046 } 1047 1048 func TestLogReorgs(t *testing.T) { 1049 var ( 1050 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1051 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1052 db = rawdb.NewMemoryDatabase() 1053 // this code generates a log 1054 code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 1055 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 1056 genesis = gspec.MustCommit(db) 1057 signer = types.LatestSigner(gspec.Config) 1058 ) 1059 1060 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 1061 defer blockchain.Stop() 1062 1063 rmLogsCh := make(chan RemovedLogsEvent) 1064 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 1065 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1066 if i == 1 { 1067 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) 1068 if err != nil { 1069 t.Fatalf("failed to create tx: %v", err) 1070 } 1071 gen.AddTx(tx) 1072 } 1073 }) 1074 if _, err := blockchain.InsertChain(chain); err != nil { 1075 t.Fatalf("failed to insert chain: %v", err) 1076 } 1077 1078 chain, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 1079 done := make(chan struct{}) 1080 go func() { 1081 ev := <-rmLogsCh 1082 if len(ev.Logs) == 0 { 1083 t.Error("expected logs") 1084 } 1085 close(done) 1086 }() 1087 if _, err := blockchain.InsertChain(chain); err != nil { 1088 t.Fatalf("failed to insert forked chain: %v", err) 1089 } 1090 timeout := time.NewTimer(1 * time.Second) 1091 defer timeout.Stop() 1092 select { 1093 case <-done: 1094 case <-timeout.C: 1095 t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") 1096 } 1097 } 1098 1099 // This EVM code generates a log when the contract is created. 1100 var logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") 1101 1102 // This test checks that log events and RemovedLogsEvent are sent 1103 // when the chain reorganizes. 1104 func TestLogRebirth(t *testing.T) { 1105 var ( 1106 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1107 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1108 db = rawdb.NewMemoryDatabase() 1109 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 1110 genesis = gspec.MustCommit(db) 1111 signer = types.LatestSigner(gspec.Config) 1112 engine = ethash.NewFaker() 1113 blockchain, _ = NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil, nil) 1114 ) 1115 1116 defer blockchain.Stop() 1117 1118 // The event channels. 1119 newLogCh := make(chan []*types.Log, 10) 1120 rmLogsCh := make(chan RemovedLogsEvent, 10) 1121 blockchain.SubscribeLogsEvent(newLogCh) 1122 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 1123 1124 // This chain contains a single log. 1125 chain, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2, func(i int, gen *BlockGen) { 1126 if i == 1 { 1127 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), logCode), signer, key1) 1128 if err != nil { 1129 t.Fatalf("failed to create tx: %v", err) 1130 } 1131 gen.AddTx(tx) 1132 } 1133 }) 1134 if _, err := blockchain.InsertChain(chain); err != nil { 1135 t.Fatalf("failed to insert chain: %v", err) 1136 } 1137 checkLogEvents(t, newLogCh, rmLogsCh, 1, 0) 1138 1139 // Generate long reorg chain containing another log. Inserting the 1140 // chain removes one log and adds one. 1141 forkChain, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2, func(i int, gen *BlockGen) { 1142 if i == 1 { 1143 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), logCode), signer, key1) 1144 if err != nil { 1145 t.Fatalf("failed to create tx: %v", err) 1146 } 1147 gen.AddTx(tx) 1148 gen.OffsetTime(-9) // higher block difficulty 1149 } 1150 }) 1151 if _, err := blockchain.InsertChain(forkChain); err != nil { 1152 t.Fatalf("failed to insert forked chain: %v", err) 1153 } 1154 checkLogEvents(t, newLogCh, rmLogsCh, 1, 1) 1155 1156 // This chain segment is rooted in the original chain, but doesn't contain any logs. 1157 // When inserting it, the canonical chain switches away from forkChain and re-emits 1158 // the log event for the old chain, as well as a RemovedLogsEvent for forkChain. 1159 newBlocks, _ := GenerateChain(params.TestChainConfig, chain[len(chain)-1], engine, db, 1, func(i int, gen *BlockGen) {}) 1160 if _, err := blockchain.InsertChain(newBlocks); err != nil { 1161 t.Fatalf("failed to insert forked chain: %v", err) 1162 } 1163 checkLogEvents(t, newLogCh, rmLogsCh, 1, 1) 1164 } 1165 1166 // This test is a variation of TestLogRebirth. It verifies that log events are emitted 1167 // when a side chain containing log events overtakes the canonical chain. 1168 func TestSideLogRebirth(t *testing.T) { 1169 var ( 1170 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1171 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1172 db = rawdb.NewMemoryDatabase() 1173 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} 1174 genesis = gspec.MustCommit(db) 1175 signer = types.LatestSigner(gspec.Config) 1176 blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 1177 ) 1178 1179 defer blockchain.Stop() 1180 1181 newLogCh := make(chan []*types.Log, 10) 1182 rmLogsCh := make(chan RemovedLogsEvent, 10) 1183 blockchain.SubscribeLogsEvent(newLogCh) 1184 blockchain.SubscribeRemovedLogsEvent(rmLogsCh) 1185 1186 chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1187 if i == 1 { 1188 gen.OffsetTime(-9) // higher block difficulty 1189 1190 } 1191 }) 1192 if _, err := blockchain.InsertChain(chain); err != nil { 1193 t.Fatalf("failed to insert forked chain: %v", err) 1194 } 1195 checkLogEvents(t, newLogCh, rmLogsCh, 0, 0) 1196 1197 // Generate side chain with lower difficulty 1198 sideChain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { 1199 if i == 1 { 1200 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), logCode), signer, key1) 1201 if err != nil { 1202 t.Fatalf("failed to create tx: %v", err) 1203 } 1204 gen.AddTx(tx) 1205 } 1206 }) 1207 if _, err := blockchain.InsertChain(sideChain); err != nil { 1208 t.Fatalf("failed to insert forked chain: %v", err) 1209 } 1210 checkLogEvents(t, newLogCh, rmLogsCh, 0, 0) 1211 1212 // Generate a new block based on side chain. 1213 newBlocks, _ := GenerateChain(params.TestChainConfig, sideChain[len(sideChain)-1], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) 1214 if _, err := blockchain.InsertChain(newBlocks); err != nil { 1215 t.Fatalf("failed to insert forked chain: %v", err) 1216 } 1217 checkLogEvents(t, newLogCh, rmLogsCh, 1, 0) 1218 } 1219 1220 func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan RemovedLogsEvent, wantNew, wantRemoved int) { 1221 t.Helper() 1222 1223 if len(logsCh) != wantNew { 1224 t.Fatalf("wrong number of log events: got %d, want %d", len(logsCh), wantNew) 1225 } 1226 if len(rmLogsCh) != wantRemoved { 1227 t.Fatalf("wrong number of removed log events: got %d, want %d", len(rmLogsCh), wantRemoved) 1228 } 1229 // Drain events. 1230 for i := 0; i < len(logsCh); i++ { 1231 <-logsCh 1232 } 1233 for i := 0; i < len(rmLogsCh); i++ { 1234 <-rmLogsCh 1235 } 1236 } 1237 1238 func TestReorgSideEvent(t *testing.T) { 1239 var ( 1240 db = rawdb.NewMemoryDatabase() 1241 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1242 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1243 gspec = &Genesis{ 1244 Config: params.TestChainConfig, 1245 Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}, 1246 } 1247 genesis = gspec.MustCommit(db) 1248 signer = types.LatestSigner(gspec.Config) 1249 ) 1250 1251 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 1252 defer blockchain.Stop() 1253 1254 chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) 1255 if _, err := blockchain.InsertChain(chain); err != nil { 1256 t.Fatalf("failed to insert chain: %v", err) 1257 } 1258 1259 replacementBlocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, gen *BlockGen) { 1260 tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), nil), signer, key1) 1261 if i == 2 { 1262 gen.OffsetTime(-9) 1263 } 1264 if err != nil { 1265 t.Fatalf("failed to create tx: %v", err) 1266 } 1267 gen.AddTx(tx) 1268 }) 1269 chainSideCh := make(chan ChainSideEvent, 64) 1270 blockchain.SubscribeChainSideEvent(chainSideCh) 1271 if _, err := blockchain.InsertChain(replacementBlocks); err != nil { 1272 t.Fatalf("failed to insert chain: %v", err) 1273 } 1274 1275 // first two block of the secondary chain are for a brief moment considered 1276 // side chains because up to that point the first one is considered the 1277 // heavier chain. 1278 expectedSideHashes := map[common.Hash]bool{ 1279 replacementBlocks[0].Hash(): true, 1280 replacementBlocks[1].Hash(): true, 1281 chain[0].Hash(): true, 1282 chain[1].Hash(): true, 1283 chain[2].Hash(): true, 1284 } 1285 1286 i := 0 1287 1288 const timeoutDura = 10 * time.Second 1289 timeout := time.NewTimer(timeoutDura) 1290 done: 1291 for { 1292 select { 1293 case ev := <-chainSideCh: 1294 block := ev.Block 1295 if _, ok := expectedSideHashes[block.Hash()]; !ok { 1296 t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash()) 1297 } 1298 i++ 1299 1300 if i == len(expectedSideHashes) { 1301 timeout.Stop() 1302 1303 break done 1304 } 1305 timeout.Reset(timeoutDura) 1306 1307 case <-timeout.C: 1308 t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent") 1309 } 1310 } 1311 1312 // make sure no more events are fired 1313 select { 1314 case e := <-chainSideCh: 1315 t.Errorf("unexpected event fired: %v", e) 1316 case <-time.After(250 * time.Millisecond): 1317 } 1318 1319 } 1320 1321 // Tests if the canonical block can be fetched from the database during chain insertion. 1322 func TestCanonicalBlockRetrieval(t *testing.T) { 1323 _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true, false) 1324 if err != nil { 1325 t.Fatalf("failed to create pristine chain: %v", err) 1326 } 1327 defer blockchain.Stop() 1328 1329 chain, _ := GenerateChain(blockchain.chainConfig, blockchain.genesisBlock, ethash.NewFaker(), blockchain.db, 10, func(i int, gen *BlockGen) {}) 1330 1331 var pend sync.WaitGroup 1332 pend.Add(len(chain)) 1333 1334 for i := range chain { 1335 go func(block *types.Block) { 1336 defer pend.Done() 1337 1338 // try to retrieve a block by its canonical hash and see if the block data can be retrieved. 1339 for { 1340 ch := rawdb.ReadCanonicalHash(blockchain.db, block.NumberU64()) 1341 if ch == (common.Hash{}) { 1342 continue // busy wait for canonical hash to be written 1343 } 1344 if ch != block.Hash() { 1345 t.Errorf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex()) 1346 return 1347 } 1348 fb := rawdb.ReadBlock(blockchain.db, ch, block.NumberU64()) 1349 if fb == nil { 1350 t.Errorf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex()) 1351 return 1352 } 1353 if fb.Hash() != block.Hash() { 1354 t.Errorf("invalid block hash for block %d, want %s, got %s", block.NumberU64(), block.Hash().Hex(), fb.Hash().Hex()) 1355 return 1356 } 1357 return 1358 } 1359 }(chain[i]) 1360 1361 if _, err := blockchain.InsertChain(types.Blocks{chain[i]}); err != nil { 1362 t.Fatalf("failed to insert block %d: %v", i, err) 1363 } 1364 } 1365 pend.Wait() 1366 } 1367 1368 func TestEIP155Transition(t *testing.T) { 1369 // Configure and generate a sample block chain 1370 var ( 1371 db = rawdb.NewMemoryDatabase() 1372 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1373 address = crypto.PubkeyToAddress(key.PublicKey) 1374 funds = big.NewInt(1000000000) 1375 deleteAddr = common.Address{1} 1376 gspec = &Genesis{ 1377 Config: ¶ms.ChainConfig{ChainID: big.NewInt(1), EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}, 1378 Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, 1379 } 1380 genesis = gspec.MustCommit(db) 1381 ) 1382 1383 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 1384 defer blockchain.Stop() 1385 1386 blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1387 var ( 1388 tx *types.Transaction 1389 err error 1390 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1391 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1392 } 1393 ) 1394 switch i { 1395 case 0: 1396 tx, err = basicTx(types.HomesteadSigner{}) 1397 if err != nil { 1398 t.Fatal(err) 1399 } 1400 block.AddTx(tx) 1401 case 2: 1402 tx, err = basicTx(types.HomesteadSigner{}) 1403 if err != nil { 1404 t.Fatal(err) 1405 } 1406 block.AddTx(tx) 1407 1408 tx, err = basicTx(types.LatestSigner(gspec.Config)) 1409 if err != nil { 1410 t.Fatal(err) 1411 } 1412 block.AddTx(tx) 1413 case 3: 1414 tx, err = basicTx(types.HomesteadSigner{}) 1415 if err != nil { 1416 t.Fatal(err) 1417 } 1418 block.AddTx(tx) 1419 1420 tx, err = basicTx(types.LatestSigner(gspec.Config)) 1421 if err != nil { 1422 t.Fatal(err) 1423 } 1424 block.AddTx(tx) 1425 } 1426 }) 1427 1428 if _, err := blockchain.InsertChain(blocks); err != nil { 1429 t.Fatal(err) 1430 } 1431 block := blockchain.GetBlockByNumber(1) 1432 if block.Transactions()[0].Protected() { 1433 t.Error("Expected block[0].txs[0] to not be replay protected") 1434 } 1435 1436 block = blockchain.GetBlockByNumber(3) 1437 if block.Transactions()[0].Protected() { 1438 t.Error("Expected block[3].txs[0] to not be replay protected") 1439 } 1440 if !block.Transactions()[1].Protected() { 1441 t.Error("Expected block[3].txs[1] to be replay protected") 1442 } 1443 if _, err := blockchain.InsertChain(blocks[4:]); err != nil { 1444 t.Fatal(err) 1445 } 1446 1447 // generate an invalid chain id transaction 1448 config := ¶ms.ChainConfig{ChainID: big.NewInt(2), EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)} 1449 blocks, _ = GenerateChain(config, blocks[len(blocks)-1], ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { 1450 var ( 1451 tx *types.Transaction 1452 err error 1453 basicTx = func(signer types.Signer) (*types.Transaction, error) { 1454 return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), 21000, new(big.Int), nil), signer, key) 1455 } 1456 ) 1457 if i == 0 { 1458 tx, err = basicTx(types.LatestSigner(config)) 1459 if err != nil { 1460 t.Fatal(err) 1461 } 1462 block.AddTx(tx) 1463 } 1464 }) 1465 _, err := blockchain.InsertChain(blocks) 1466 if err != types.ErrInvalidChainId { 1467 t.Error("expected error:", types.ErrInvalidChainId) 1468 } 1469 } 1470 1471 func TestEIP161AccountRemoval(t *testing.T) { 1472 // Configure and generate a sample block chain 1473 var ( 1474 db = rawdb.NewMemoryDatabase() 1475 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1476 address = crypto.PubkeyToAddress(key.PublicKey) 1477 funds = big.NewInt(1000000000) 1478 theAddr = common.Address{1} 1479 gspec = &Genesis{ 1480 Config: ¶ms.ChainConfig{ 1481 ChainID: big.NewInt(1), 1482 HomesteadBlock: new(big.Int), 1483 EIP155Block: new(big.Int), 1484 EIP150Block: new(big.Int), 1485 EIP158Block: big.NewInt(2), 1486 }, 1487 Alloc: GenesisAlloc{address: {Balance: funds}}, 1488 } 1489 genesis = gspec.MustCommit(db) 1490 ) 1491 blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 1492 defer blockchain.Stop() 1493 1494 blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, block *BlockGen) { 1495 var ( 1496 tx *types.Transaction 1497 err error 1498 signer = types.LatestSigner(gspec.Config) 1499 ) 1500 switch i { 1501 case 0: 1502 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1503 case 1: 1504 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1505 case 2: 1506 tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), 21000, new(big.Int), nil), signer, key) 1507 } 1508 if err != nil { 1509 t.Fatal(err) 1510 } 1511 block.AddTx(tx) 1512 }) 1513 // account must exist pre eip 161 1514 if _, err := blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil { 1515 t.Fatal(err) 1516 } 1517 if st, _ := blockchain.State(); !st.Exist(theAddr) { 1518 t.Error("expected account to exist") 1519 } 1520 1521 // account needs to be deleted post eip 161 1522 if _, err := blockchain.InsertChain(types.Blocks{blocks[1]}); err != nil { 1523 t.Fatal(err) 1524 } 1525 if st, _ := blockchain.State(); st.Exist(theAddr) { 1526 t.Error("account should not exist") 1527 } 1528 1529 // account mustn't be created post eip 161 1530 if _, err := blockchain.InsertChain(types.Blocks{blocks[2]}); err != nil { 1531 t.Fatal(err) 1532 } 1533 if st, _ := blockchain.State(); st.Exist(theAddr) { 1534 t.Error("account should not exist") 1535 } 1536 } 1537 1538 // This is a regression test (i.e. as weird as it is, don't delete it ever), which 1539 // tests that under weird reorg conditions the blockchain and its internal header- 1540 // chain return the same latest block/header. 1541 // 1542 // https://github.com/fff-chain/go-fff/pull/15941 1543 func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { 1544 // Generate a canonical chain to act as the main dataset 1545 engine := ethash.NewFaker() 1546 1547 db := rawdb.NewMemoryDatabase() 1548 genesis := new(Genesis).MustCommit(db) 1549 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1550 1551 // Generate a bunch of fork blocks, each side forking from the canonical chain 1552 forks := make([]*types.Block, len(blocks)) 1553 for i := 0; i < len(forks); i++ { 1554 parent := genesis 1555 if i > 0 { 1556 parent = blocks[i-1] 1557 } 1558 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1559 forks[i] = fork[0] 1560 } 1561 // Import the canonical and fork chain side by side, verifying the current block 1562 // and current header consistency 1563 diskdb := rawdb.NewMemoryDatabase() 1564 new(Genesis).MustCommit(diskdb) 1565 1566 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) 1567 if err != nil { 1568 t.Fatalf("failed to create tester chain: %v", err) 1569 } 1570 for i := 0; i < len(blocks); i++ { 1571 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1572 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1573 } 1574 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1575 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]) 1576 } 1577 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1578 t.Fatalf(" fork %d: failed to insert into chain: %v", i, err) 1579 } 1580 if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { 1581 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]) 1582 } 1583 } 1584 } 1585 1586 // Tests that importing small side forks doesn't leave junk in the trie database 1587 // cache (which would eventually cause memory issues). 1588 func TestTrieForkGC(t *testing.T) { 1589 // Generate a canonical chain to act as the main dataset 1590 engine := ethash.NewFaker() 1591 1592 db := rawdb.NewMemoryDatabase() 1593 genesis := new(Genesis).MustCommit(db) 1594 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TestTriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1595 1596 // Generate a bunch of fork blocks, each side forking from the canonical chain 1597 forks := make([]*types.Block, len(blocks)) 1598 for i := 0; i < len(forks); i++ { 1599 parent := genesis 1600 if i > 0 { 1601 parent = blocks[i-1] 1602 } 1603 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1604 forks[i] = fork[0] 1605 } 1606 // Import the canonical and fork chain side by side, forcing the trie cache to cache both 1607 diskdb := rawdb.NewMemoryDatabase() 1608 new(Genesis).MustCommit(diskdb) 1609 1610 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) 1611 if err != nil { 1612 t.Fatalf("failed to create tester chain: %v", err) 1613 } 1614 for i := 0; i < len(blocks); i++ { 1615 if _, err := chain.InsertChain(blocks[i : i+1]); err != nil { 1616 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1617 } 1618 if _, err := chain.InsertChain(forks[i : i+1]); err != nil { 1619 t.Fatalf("fork %d: failed to insert into chain: %v", i, err) 1620 } 1621 } 1622 // Dereference all the recent tries and ensure no past trie is left in 1623 for i := 0; i < TestTriesInMemory; i++ { 1624 chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root()) 1625 chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root()) 1626 } 1627 if len(chain.stateCache.TrieDB().Nodes()) > 0 { 1628 t.Fatalf("stale tries still alive after garbase collection") 1629 } 1630 } 1631 1632 // Tests that doing large reorgs works even if the state associated with the 1633 // forking point is not available any more. 1634 func TestLargeReorgTrieGC(t *testing.T) { 1635 // Generate the original common chain segment and the two competing forks 1636 engine := ethash.NewFaker() 1637 1638 db := rawdb.NewMemoryDatabase() 1639 genesis := new(Genesis).MustCommit(db) 1640 1641 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1642 original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*TestTriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) 1643 competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*TestTriesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) 1644 1645 // Import the shared chain and the original canonical one 1646 diskdb := rawdb.NewMemoryDatabase() 1647 new(Genesis).MustCommit(diskdb) 1648 1649 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) 1650 if err != nil { 1651 t.Fatalf("failed to create tester chain: %v", err) 1652 } 1653 if _, err := chain.InsertChain(shared); err != nil { 1654 t.Fatalf("failed to insert shared chain: %v", err) 1655 } 1656 if _, err := chain.InsertChain(original); err != nil { 1657 t.Fatalf("failed to insert original chain: %v", err) 1658 } 1659 // Ensure that the state associated with the forking point is pruned away 1660 if node, _ := chain.stateCache.TrieDB().Node(shared[len(shared)-1].Root()); node != nil { 1661 t.Fatalf("common-but-old ancestor still cache") 1662 } 1663 // Import the competitor chain without exceeding the canonical's TD and ensure 1664 // we have not processed any of the blocks (protection against malicious blocks) 1665 if _, err := chain.InsertChain(competitor[:len(competitor)-2]); err != nil { 1666 t.Fatalf("failed to insert competitor chain: %v", err) 1667 } 1668 for i, block := range competitor[:len(competitor)-2] { 1669 if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1670 t.Fatalf("competitor %d: low TD chain became processed", i) 1671 } 1672 } 1673 // Import the head of the competitor chain, triggering the reorg and ensure we 1674 // successfully reprocess all the stashed away blocks. 1675 if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil { 1676 t.Fatalf("failed to finalize competitor chain: %v", err) 1677 } 1678 for i, block := range competitor[:len(competitor)-TestTriesInMemory] { 1679 if node, err := chain.stateCache.TrieDB().Node(block.Root()); node != nil { 1680 t.Fatalf("competitor %d: competing chain state missing, err: %v", i, err) 1681 } 1682 } 1683 } 1684 1685 func TestBlockchainRecovery(t *testing.T) { 1686 // Configure and generate a sample block chain 1687 var ( 1688 gendb = rawdb.NewMemoryDatabase() 1689 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1690 address = crypto.PubkeyToAddress(key.PublicKey) 1691 funds = big.NewInt(1000000000) 1692 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 1693 genesis = gspec.MustCommit(gendb) 1694 ) 1695 height := uint64(1024) 1696 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil) 1697 1698 // Import the chain as a ancient-first node and ensure all pointers are updated 1699 frdir, err := ioutil.TempDir("", "") 1700 if err != nil { 1701 t.Fatalf("failed to create temp freezer dir: %v", err) 1702 } 1703 defer os.Remove(frdir) 1704 1705 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false) 1706 if err != nil { 1707 t.Fatalf("failed to create temp freezer db: %v", err) 1708 } 1709 gspec.MustCommit(ancientDb) 1710 ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 1711 1712 headers := make([]*types.Header, len(blocks)) 1713 for i, block := range blocks { 1714 headers[i] = block.Header() 1715 } 1716 if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { 1717 t.Fatalf("failed to insert header %d: %v", n, err) 1718 } 1719 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { 1720 t.Fatalf("failed to insert receipt %d: %v", n, err) 1721 } 1722 rawdb.WriteLastPivotNumber(ancientDb, blocks[len(blocks)-1].NumberU64()) // Force fast sync behavior 1723 ancient.Stop() 1724 1725 // Destroy head fast block manually 1726 midBlock := blocks[len(blocks)/2] 1727 rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash()) 1728 1729 // Reopen broken blockchain again 1730 ancient, _ = NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 1731 defer ancient.Stop() 1732 if num := ancient.CurrentBlock().NumberU64(); num != 0 { 1733 t.Errorf("head block mismatch: have #%v, want #%v", num, 0) 1734 } 1735 if num := ancient.CurrentFastBlock().NumberU64(); num != midBlock.NumberU64() { 1736 t.Errorf("head fast-block mismatch: have #%v, want #%v", num, midBlock.NumberU64()) 1737 } 1738 if num := ancient.CurrentHeader().Number.Uint64(); num != midBlock.NumberU64() { 1739 t.Errorf("head header mismatch: have #%v, want #%v", num, midBlock.NumberU64()) 1740 } 1741 } 1742 1743 func TestIncompleteAncientReceiptChainInsertion(t *testing.T) { 1744 // Configure and generate a sample block chain 1745 var ( 1746 gendb = rawdb.NewMemoryDatabase() 1747 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1748 address = crypto.PubkeyToAddress(key.PublicKey) 1749 funds = big.NewInt(1000000000) 1750 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 1751 genesis = gspec.MustCommit(gendb) 1752 ) 1753 height := uint64(1024) 1754 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), nil) 1755 1756 // Import the chain as a ancient-first node and ensure all pointers are updated 1757 frdir, err := ioutil.TempDir("", "") 1758 if err != nil { 1759 t.Fatalf("failed to create temp freezer dir: %v", err) 1760 } 1761 defer os.Remove(frdir) 1762 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false) 1763 if err != nil { 1764 t.Fatalf("failed to create temp freezer db: %v", err) 1765 } 1766 gspec.MustCommit(ancientDb) 1767 ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) 1768 defer ancient.Stop() 1769 1770 headers := make([]*types.Header, len(blocks)) 1771 for i, block := range blocks { 1772 headers[i] = block.Header() 1773 } 1774 if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { 1775 t.Fatalf("failed to insert header %d: %v", n, err) 1776 } 1777 // Abort ancient receipt chain insertion deliberately 1778 ancient.terminateInsert = func(hash common.Hash, number uint64) bool { 1779 return number == blocks[len(blocks)/2].NumberU64() 1780 } 1781 previousFastBlock := ancient.CurrentFastBlock() 1782 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err == nil { 1783 t.Fatalf("failed to insert receipt %d: %v", n, err) 1784 } 1785 if ancient.CurrentFastBlock().NumberU64() != previousFastBlock.NumberU64() { 1786 t.Fatalf("failed to rollback ancient data, want %d, have %d", previousFastBlock.NumberU64(), ancient.CurrentFastBlock().NumberU64()) 1787 } 1788 if frozen, err := ancient.db.Ancients(); err != nil || frozen != 1 { 1789 t.Fatalf("failed to truncate ancient data") 1790 } 1791 ancient.terminateInsert = nil 1792 if n, err := ancient.InsertReceiptChain(blocks, receipts, uint64(3*len(blocks)/4)); err != nil { 1793 t.Fatalf("failed to insert receipt %d: %v", n, err) 1794 } 1795 if ancient.CurrentFastBlock().NumberU64() != blocks[len(blocks)-1].NumberU64() { 1796 t.Fatalf("failed to insert ancient recept chain after rollback") 1797 } 1798 } 1799 1800 // Tests that importing a very large side fork, which is larger than the canon chain, 1801 // but where the difficulty per block is kept low: this means that it will not 1802 // overtake the 'canon' chain until after it's passed canon by about 200 blocks. 1803 // 1804 // Details at: 1805 // - https://github.com/fff-chain/go-fff/issues/18977 1806 // - https://github.com/fff-chain/go-fff/pull/18988 1807 func TestLowDiffLongChain(t *testing.T) { 1808 // Generate a canonical chain to act as the main dataset 1809 engine := ethash.NewFaker() 1810 db := rawdb.NewMemoryDatabase() 1811 genesis := new(Genesis).MustCommit(db) 1812 1813 // We must use a pretty long chain to ensure that the fork doesn't overtake us 1814 // until after at least 128 blocks post tip 1815 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 6*TestTriesInMemory, func(i int, b *BlockGen) { 1816 b.SetCoinbase(common.Address{1}) 1817 b.OffsetTime(-9) 1818 }) 1819 1820 // Import the canonical chain 1821 diskdb := rawdb.NewMemoryDatabase() 1822 new(Genesis).MustCommit(diskdb) 1823 1824 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) 1825 if err != nil { 1826 t.Fatalf("failed to create tester chain: %v", err) 1827 } 1828 if n, err := chain.InsertChain(blocks); err != nil { 1829 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 1830 } 1831 // Generate fork chain, starting from an early block 1832 parent := blocks[10] 1833 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 8*TestTriesInMemory, func(i int, b *BlockGen) { 1834 b.SetCoinbase(common.Address{2}) 1835 }) 1836 1837 // And now import the fork 1838 if i, err := chain.InsertChain(fork); err != nil { 1839 t.Fatalf("block %d: failed to insert into chain: %v", i, err) 1840 } 1841 head := chain.CurrentBlock() 1842 if got := fork[len(fork)-1].Hash(); got != head.Hash() { 1843 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 1844 } 1845 // Sanity check that all the canonical numbers are present 1846 header := chain.CurrentHeader() 1847 for number := head.NumberU64(); number > 0; number-- { 1848 if hash := chain.GetHeaderByNumber(number).Hash(); hash != header.Hash() { 1849 t.Fatalf("header %d: canonical hash mismatch: have %x, want %x", number, hash, header.Hash()) 1850 } 1851 header = chain.GetHeader(header.ParentHash, number-1) 1852 } 1853 } 1854 1855 // Tests that importing a sidechain (S), where 1856 // - S is sidechain, containing blocks [Sn...Sm] 1857 // - C is canon chain, containing blocks [G..Cn..Cm] 1858 // - A common ancestor is placed at prune-point + blocksBetweenCommonAncestorAndPruneblock 1859 // - The sidechain S is prepended with numCanonBlocksInSidechain blocks from the canon chain 1860 func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommonAncestorAndPruneblock int) { 1861 1862 // Generate a canonical chain to act as the main dataset 1863 engine := ethash.NewFaker() 1864 db := rawdb.NewMemoryDatabase() 1865 genesis := new(Genesis).MustCommit(db) 1866 1867 // Generate and import the canonical chain 1868 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TestTriesInMemory, nil) 1869 diskdb := rawdb.NewMemoryDatabase() 1870 new(Genesis).MustCommit(diskdb) 1871 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) 1872 if err != nil { 1873 t.Fatalf("failed to create tester chain: %v", err) 1874 } 1875 if n, err := chain.InsertChain(blocks); err != nil { 1876 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 1877 } 1878 1879 lastPrunedIndex := len(blocks) - TestTriesInMemory - 1 1880 lastPrunedBlock := blocks[lastPrunedIndex-1] 1881 firstNonPrunedBlock := blocks[len(blocks)-TestTriesInMemory] 1882 1883 // Verify pruning of lastPrunedBlock 1884 if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) { 1885 t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64()) 1886 } 1887 // Verify firstNonPrunedBlock is not pruned 1888 if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) { 1889 t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64()) 1890 } 1891 // Generate the sidechain 1892 // First block should be a known block, block after should be a pruned block. So 1893 // canon(pruned), side, side... 1894 1895 // Generate fork chain, make it longer than canon 1896 parentIndex := lastPrunedIndex + blocksBetweenCommonAncestorAndPruneblock 1897 parent := blocks[parentIndex] 1898 fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 2*TestTriesInMemory, func(i int, b *BlockGen) { 1899 b.SetCoinbase(common.Address{2}) 1900 }) 1901 // Prepend the parent(s) 1902 var sidechain []*types.Block 1903 for i := numCanonBlocksInSidechain; i > 0; i-- { 1904 sidechain = append(sidechain, blocks[parentIndex+1-i]) 1905 } 1906 sidechain = append(sidechain, fork...) 1907 _, err = chain.InsertChain(sidechain) 1908 if err != nil { 1909 t.Errorf("Got error, %v", err) 1910 } 1911 head := chain.CurrentBlock() 1912 if got := fork[len(fork)-1].Hash(); got != head.Hash() { 1913 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 1914 } 1915 } 1916 1917 // Tests that importing a sidechain (S), where 1918 // - S is sidechain, containing blocks [Sn...Sm] 1919 // - C is canon chain, containing blocks [G..Cn..Cm] 1920 // - The common ancestor Cc is pruned 1921 // - The first block in S: Sn, is == Cn 1922 // That is: the sidechain for import contains some blocks already present in canon chain. 1923 // So the blocks are 1924 // [ Cn, Cn+1, Cc, Sn+3 ... Sm] 1925 // ^ ^ ^ pruned 1926 func TestPrunedImportSide(t *testing.T) { 1927 //glogger := log.NewGlogHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false))) 1928 //glogger.Verbosity(3) 1929 //log.Root().SetHandler(log.Handler(glogger)) 1930 testSideImport(t, 3, 3) 1931 testSideImport(t, 3, -3) 1932 testSideImport(t, 10, 0) 1933 testSideImport(t, 1, 10) 1934 testSideImport(t, 1, -10) 1935 } 1936 1937 func TestInsertKnownHeaders(t *testing.T) { testInsertKnownChainData(t, "headers") } 1938 func TestInsertKnownReceiptChain(t *testing.T) { testInsertKnownChainData(t, "receipts") } 1939 func TestInsertKnownBlocks(t *testing.T) { testInsertKnownChainData(t, "blocks") } 1940 1941 func testInsertKnownChainData(t *testing.T, typ string) { 1942 engine := ethash.NewFaker() 1943 1944 db := rawdb.NewMemoryDatabase() 1945 genesis := new(Genesis).MustCommit(db) 1946 1947 blocks, receipts := GenerateChain(params.TestChainConfig, genesis, engine, db, 32, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1948 // A longer chain but total difficulty is lower. 1949 blocks2, receipts2 := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], engine, db, 65, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) 1950 // A shorter chain but total difficulty is higher. 1951 blocks3, receipts3 := GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], engine, db, 64, func(i int, b *BlockGen) { 1952 b.SetCoinbase(common.Address{1}) 1953 b.OffsetTime(-9) // A higher difficulty 1954 }) 1955 // Import the shared chain and the original canonical one 1956 dir, err := ioutil.TempDir("", "") 1957 if err != nil { 1958 t.Fatalf("failed to create temp freezer dir: %v", err) 1959 } 1960 defer os.Remove(dir) 1961 chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), dir, "", false, false, false) 1962 if err != nil { 1963 t.Fatalf("failed to create temp freezer db: %v", err) 1964 } 1965 new(Genesis).MustCommit(chaindb) 1966 defer os.RemoveAll(dir) 1967 1968 chain, err := NewBlockChain(chaindb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) 1969 if err != nil { 1970 t.Fatalf("failed to create tester chain: %v", err) 1971 } 1972 1973 var ( 1974 inserter func(blocks []*types.Block, receipts []types.Receipts) error 1975 asserter func(t *testing.T, block *types.Block) 1976 ) 1977 if typ == "headers" { 1978 inserter = func(blocks []*types.Block, receipts []types.Receipts) error { 1979 headers := make([]*types.Header, 0, len(blocks)) 1980 for _, block := range blocks { 1981 headers = append(headers, block.Header()) 1982 } 1983 _, err := chain.InsertHeaderChain(headers, 1) 1984 return err 1985 } 1986 asserter = func(t *testing.T, block *types.Block) { 1987 if chain.CurrentHeader().Hash() != block.Hash() { 1988 t.Fatalf("current head header mismatch, have %v, want %v", chain.CurrentHeader().Hash().Hex(), block.Hash().Hex()) 1989 } 1990 } 1991 } else if typ == "receipts" { 1992 inserter = func(blocks []*types.Block, receipts []types.Receipts) error { 1993 headers := make([]*types.Header, 0, len(blocks)) 1994 for _, block := range blocks { 1995 headers = append(headers, block.Header()) 1996 } 1997 _, err := chain.InsertHeaderChain(headers, 1) 1998 if err != nil { 1999 return err 2000 } 2001 _, err = chain.InsertReceiptChain(blocks, receipts, 0) 2002 return err 2003 } 2004 asserter = func(t *testing.T, block *types.Block) { 2005 if chain.CurrentFastBlock().Hash() != block.Hash() { 2006 t.Fatalf("current head fast block mismatch, have %v, want %v", chain.CurrentFastBlock().Hash().Hex(), block.Hash().Hex()) 2007 } 2008 } 2009 } else { 2010 inserter = func(blocks []*types.Block, receipts []types.Receipts) error { 2011 _, err := chain.InsertChain(blocks) 2012 return err 2013 } 2014 asserter = func(t *testing.T, block *types.Block) { 2015 if chain.CurrentBlock().Hash() != block.Hash() { 2016 t.Fatalf("current head block mismatch, have %v, want %v", chain.CurrentBlock().Hash().Hex(), block.Hash().Hex()) 2017 } 2018 } 2019 } 2020 2021 if err := inserter(blocks, receipts); err != nil { 2022 t.Fatalf("failed to insert chain data: %v", err) 2023 } 2024 2025 // Reimport the chain data again. All the imported 2026 // chain data are regarded "known" data. 2027 if err := inserter(blocks, receipts); err != nil { 2028 t.Fatalf("failed to insert chain data: %v", err) 2029 } 2030 asserter(t, blocks[len(blocks)-1]) 2031 2032 // Import a long canonical chain with some known data as prefix. 2033 rollback := blocks[len(blocks)/2].NumberU64() 2034 2035 chain.SetHead(rollback - 1) 2036 if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { 2037 t.Fatalf("failed to insert chain data: %v", err) 2038 } 2039 asserter(t, blocks2[len(blocks2)-1]) 2040 2041 // Import a heavier shorter but higher total difficulty chain with some known data as prefix. 2042 if err := inserter(append(blocks, blocks3...), append(receipts, receipts3...)); err != nil { 2043 t.Fatalf("failed to insert chain data: %v", err) 2044 } 2045 asserter(t, blocks3[len(blocks3)-1]) 2046 2047 // Import a longer but lower total difficulty chain with some known data as prefix. 2048 if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { 2049 t.Fatalf("failed to insert chain data: %v", err) 2050 } 2051 // The head shouldn't change. 2052 asserter(t, blocks3[len(blocks3)-1]) 2053 2054 // Rollback the heavier chain and re-insert the longer chain again 2055 chain.SetHead(rollback - 1) 2056 if err := inserter(append(blocks, blocks2...), append(receipts, receipts2...)); err != nil { 2057 t.Fatalf("failed to insert chain data: %v", err) 2058 } 2059 asserter(t, blocks2[len(blocks2)-1]) 2060 } 2061 2062 // getLongAndShortChains returns two chains, 2063 // A is longer, B is heavier 2064 func getLongAndShortChains() (*BlockChain, []*types.Block, []*types.Block, error) { 2065 // Generate a canonical chain to act as the main dataset 2066 engine := ethash.NewFaker() 2067 db := rawdb.NewMemoryDatabase() 2068 genesis := new(Genesis).MustCommit(db) 2069 2070 // Generate and import the canonical chain, 2071 // Offset the time, to keep the difficulty low 2072 longChain, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 80, func(i int, b *BlockGen) { 2073 b.SetCoinbase(common.Address{1}) 2074 }) 2075 diskdb := rawdb.NewMemoryDatabase() 2076 new(Genesis).MustCommit(diskdb) 2077 2078 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) 2079 if err != nil { 2080 return nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err) 2081 } 2082 2083 // Generate fork chain, make it shorter than canon, with common ancestor pretty early 2084 parentIndex := 3 2085 parent := longChain[parentIndex] 2086 heavyChain, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 75, func(i int, b *BlockGen) { 2087 b.SetCoinbase(common.Address{2}) 2088 b.OffsetTime(-9) 2089 }) 2090 // Verify that the test is sane 2091 var ( 2092 longerTd = new(big.Int) 2093 shorterTd = new(big.Int) 2094 ) 2095 for index, b := range longChain { 2096 longerTd.Add(longerTd, b.Difficulty()) 2097 if index <= parentIndex { 2098 shorterTd.Add(shorterTd, b.Difficulty()) 2099 } 2100 } 2101 for _, b := range heavyChain { 2102 shorterTd.Add(shorterTd, b.Difficulty()) 2103 } 2104 if shorterTd.Cmp(longerTd) <= 0 { 2105 return nil, nil, nil, fmt.Errorf("Test is moot, heavyChain td (%v) must be larger than canon td (%v)", shorterTd, longerTd) 2106 } 2107 longerNum := longChain[len(longChain)-1].NumberU64() 2108 shorterNum := heavyChain[len(heavyChain)-1].NumberU64() 2109 if shorterNum >= longerNum { 2110 return nil, nil, nil, fmt.Errorf("Test is moot, heavyChain num (%v) must be lower than canon num (%v)", shorterNum, longerNum) 2111 } 2112 return chain, longChain, heavyChain, nil 2113 } 2114 2115 // TestReorgToShorterRemovesCanonMapping tests that if we 2116 // 1. Have a chain [0 ... N .. X] 2117 // 2. Reorg to shorter but heavier chain [0 ... N ... Y] 2118 // 3. Then there should be no canon mapping for the block at height X 2119 func TestReorgToShorterRemovesCanonMapping(t *testing.T) { 2120 chain, canonblocks, sideblocks, err := getLongAndShortChains() 2121 if err != nil { 2122 t.Fatal(err) 2123 } 2124 if n, err := chain.InsertChain(canonblocks); err != nil { 2125 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2126 } 2127 canonNum := chain.CurrentBlock().NumberU64() 2128 _, err = chain.InsertChain(sideblocks) 2129 if err != nil { 2130 t.Errorf("Got error, %v", err) 2131 } 2132 head := chain.CurrentBlock() 2133 if got := sideblocks[len(sideblocks)-1].Hash(); got != head.Hash() { 2134 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 2135 } 2136 // We have now inserted a sidechain. 2137 if blockByNum := chain.GetBlockByNumber(canonNum); blockByNum != nil { 2138 t.Errorf("expected block to be gone: %v", blockByNum.NumberU64()) 2139 } 2140 if headerByNum := chain.GetHeaderByNumber(canonNum); headerByNum != nil { 2141 t.Errorf("expected header to be gone: %v", headerByNum.Number.Uint64()) 2142 } 2143 } 2144 2145 // TestReorgToShorterRemovesCanonMappingHeaderChain is the same scenario 2146 // as TestReorgToShorterRemovesCanonMapping, but applied on headerchain 2147 // imports -- that is, for fast sync 2148 func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) { 2149 chain, canonblocks, sideblocks, err := getLongAndShortChains() 2150 if err != nil { 2151 t.Fatal(err) 2152 } 2153 // Convert into headers 2154 canonHeaders := make([]*types.Header, len(canonblocks)) 2155 for i, block := range canonblocks { 2156 canonHeaders[i] = block.Header() 2157 } 2158 if n, err := chain.InsertHeaderChain(canonHeaders, 0); err != nil { 2159 t.Fatalf("header %d: failed to insert into chain: %v", n, err) 2160 } 2161 canonNum := chain.CurrentHeader().Number.Uint64() 2162 sideHeaders := make([]*types.Header, len(sideblocks)) 2163 for i, block := range sideblocks { 2164 sideHeaders[i] = block.Header() 2165 } 2166 if n, err := chain.InsertHeaderChain(sideHeaders, 0); err != nil { 2167 t.Fatalf("header %d: failed to insert into chain: %v", n, err) 2168 } 2169 head := chain.CurrentHeader() 2170 if got := sideblocks[len(sideblocks)-1].Hash(); got != head.Hash() { 2171 t.Fatalf("head wrong, expected %x got %x", head.Hash(), got) 2172 } 2173 // We have now inserted a sidechain. 2174 if blockByNum := chain.GetBlockByNumber(canonNum); blockByNum != nil { 2175 t.Errorf("expected block to be gone: %v", blockByNum.NumberU64()) 2176 } 2177 if headerByNum := chain.GetHeaderByNumber(canonNum); headerByNum != nil { 2178 t.Errorf("expected header to be gone: %v", headerByNum.Number.Uint64()) 2179 } 2180 } 2181 2182 func TestTransactionIndices(t *testing.T) { 2183 // Configure and generate a sample block chain 2184 var ( 2185 gendb = rawdb.NewMemoryDatabase() 2186 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 2187 address = crypto.PubkeyToAddress(key.PublicKey) 2188 funds = big.NewInt(1000000000) 2189 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 2190 genesis = gspec.MustCommit(gendb) 2191 signer = types.LatestSigner(gspec.Config) 2192 ) 2193 height := uint64(128) 2194 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), func(i int, block *BlockGen) { 2195 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key) 2196 if err != nil { 2197 panic(err) 2198 } 2199 block.AddTx(tx) 2200 }) 2201 blocks2, _ := GenerateChain(gspec.Config, blocks[len(blocks)-1], ethash.NewFaker(), gendb, 10, nil) 2202 2203 check := func(tail *uint64, chain *BlockChain) { 2204 stored := rawdb.ReadTxIndexTail(chain.db) 2205 if tail == nil && stored != nil { 2206 t.Fatalf("Oldest indexded block mismatch, want nil, have %d", *stored) 2207 } 2208 if tail != nil && *stored != *tail { 2209 t.Fatalf("Oldest indexded block mismatch, want %d, have %d", *tail, *stored) 2210 } 2211 if tail != nil { 2212 for i := *tail; i <= chain.CurrentBlock().NumberU64(); i++ { 2213 block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i) 2214 if block.Transactions().Len() == 0 { 2215 continue 2216 } 2217 for _, tx := range block.Transactions() { 2218 if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index == nil { 2219 t.Fatalf("Miss transaction indice, number %d hash %s", i, tx.Hash().Hex()) 2220 } 2221 } 2222 } 2223 for i := uint64(0); i < *tail; i++ { 2224 block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i) 2225 if block.Transactions().Len() == 0 { 2226 continue 2227 } 2228 for _, tx := range block.Transactions() { 2229 if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index != nil { 2230 t.Fatalf("Transaction indice should be deleted, number %d hash %s", i, tx.Hash().Hex()) 2231 } 2232 } 2233 } 2234 } 2235 } 2236 frdir, err := ioutil.TempDir("", "") 2237 if err != nil { 2238 t.Fatalf("failed to create temp freezer dir: %v", err) 2239 } 2240 defer os.Remove(frdir) 2241 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false) 2242 if err != nil { 2243 t.Fatalf("failed to create temp freezer db: %v", err) 2244 } 2245 gspec.MustCommit(ancientDb) 2246 2247 // Import all blocks into ancient db 2248 l := uint64(0) 2249 chain, err := NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l) 2250 if err != nil { 2251 t.Fatalf("failed to create tester chain: %v", err) 2252 } 2253 headers := make([]*types.Header, len(blocks)) 2254 for i, block := range blocks { 2255 headers[i] = block.Header() 2256 } 2257 if n, err := chain.InsertHeaderChain(headers, 0); err != nil { 2258 t.Fatalf("failed to insert header %d: %v", n, err) 2259 } 2260 if n, err := chain.InsertReceiptChain(blocks, receipts, 128); err != nil { 2261 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2262 } 2263 chain.Stop() 2264 ancientDb.Close() 2265 2266 // Init block chain with external ancients, check all needed indices has been indexed. 2267 limit := []uint64{0, 32, 64, 128} 2268 for _, l := range limit { 2269 ancientDb, err = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false) 2270 if err != nil { 2271 t.Fatalf("failed to create temp freezer db: %v", err) 2272 } 2273 gspec.MustCommit(ancientDb) 2274 chain, err = NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l) 2275 if err != nil { 2276 t.Fatalf("failed to create tester chain: %v", err) 2277 } 2278 time.Sleep(50 * time.Millisecond) // Wait for indices initialisation 2279 var tail uint64 2280 if l != 0 { 2281 tail = uint64(128) - l + 1 2282 } 2283 check(&tail, chain) 2284 chain.Stop() 2285 ancientDb.Close() 2286 } 2287 2288 // Reconstruct a block chain which only reserves HEAD-64 tx indices 2289 ancientDb, err = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false) 2290 if err != nil { 2291 t.Fatalf("failed to create temp freezer db: %v", err) 2292 } 2293 gspec.MustCommit(ancientDb) 2294 2295 limit = []uint64{0, 64 /* drop stale */, 32 /* shorten history */, 64 /* extend history */, 0 /* restore all */} 2296 tails := []uint64{0, 67 /* 130 - 64 + 1 */, 100 /* 131 - 32 + 1 */, 69 /* 132 - 64 + 1 */, 0} 2297 for i, l := range limit { 2298 chain, err = NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l) 2299 if err != nil { 2300 t.Fatalf("failed to create tester chain: %v", err) 2301 } 2302 chain.InsertChain(blocks2[i : i+1]) // Feed chain a higher block to trigger indices updater. 2303 time.Sleep(50 * time.Millisecond) // Wait for indices initialisation 2304 check(&tails[i], chain) 2305 chain.Stop() 2306 } 2307 } 2308 2309 func TestSkipStaleTxIndicesInFastSync(t *testing.T) { 2310 // Configure and generate a sample block chain 2311 var ( 2312 gendb = rawdb.NewMemoryDatabase() 2313 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 2314 address = crypto.PubkeyToAddress(key.PublicKey) 2315 funds = big.NewInt(1000000000) 2316 gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} 2317 genesis = gspec.MustCommit(gendb) 2318 signer = types.LatestSigner(gspec.Config) 2319 ) 2320 height := uint64(128) 2321 blocks, receipts := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, int(height), func(i int, block *BlockGen) { 2322 tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key) 2323 if err != nil { 2324 panic(err) 2325 } 2326 block.AddTx(tx) 2327 }) 2328 2329 check := func(tail *uint64, chain *BlockChain) { 2330 stored := rawdb.ReadTxIndexTail(chain.db) 2331 if tail == nil && stored != nil { 2332 t.Fatalf("Oldest indexded block mismatch, want nil, have %d", *stored) 2333 } 2334 if tail != nil && *stored != *tail { 2335 t.Fatalf("Oldest indexded block mismatch, want %d, have %d", *tail, *stored) 2336 } 2337 if tail != nil { 2338 for i := *tail; i <= chain.CurrentBlock().NumberU64(); i++ { 2339 block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i) 2340 if block.Transactions().Len() == 0 { 2341 continue 2342 } 2343 for _, tx := range block.Transactions() { 2344 if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index == nil { 2345 t.Fatalf("Miss transaction indice, number %d hash %s", i, tx.Hash().Hex()) 2346 } 2347 } 2348 } 2349 for i := uint64(0); i < *tail; i++ { 2350 block := rawdb.ReadBlock(chain.db, rawdb.ReadCanonicalHash(chain.db, i), i) 2351 if block.Transactions().Len() == 0 { 2352 continue 2353 } 2354 for _, tx := range block.Transactions() { 2355 if index := rawdb.ReadTxLookupEntry(chain.db, tx.Hash()); index != nil { 2356 t.Fatalf("Transaction indice should be deleted, number %d hash %s", i, tx.Hash().Hex()) 2357 } 2358 } 2359 } 2360 } 2361 } 2362 2363 frdir, err := ioutil.TempDir("", "") 2364 if err != nil { 2365 t.Fatalf("failed to create temp freezer dir: %v", err) 2366 } 2367 defer os.Remove(frdir) 2368 ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false, false, false) 2369 if err != nil { 2370 t.Fatalf("failed to create temp freezer db: %v", err) 2371 } 2372 gspec.MustCommit(ancientDb) 2373 2374 // Import all blocks into ancient db, only HEAD-32 indices are kept. 2375 l := uint64(32) 2376 chain, err := NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l) 2377 if err != nil { 2378 t.Fatalf("failed to create tester chain: %v", err) 2379 } 2380 headers := make([]*types.Header, len(blocks)) 2381 for i, block := range blocks { 2382 headers[i] = block.Header() 2383 } 2384 if n, err := chain.InsertHeaderChain(headers, 0); err != nil { 2385 t.Fatalf("failed to insert header %d: %v", n, err) 2386 } 2387 // The indices before ancient-N(32) should be ignored. After that all blocks should be indexed. 2388 if n, err := chain.InsertReceiptChain(blocks, receipts, 64); err != nil { 2389 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2390 } 2391 tail := uint64(32) 2392 check(&tail, chain) 2393 } 2394 2395 // Benchmarks large blocks with value transfers to non-existing accounts 2396 func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks int, recipientFn func(uint64) common.Address, dataFn func(uint64) []byte) { 2397 var ( 2398 signer = types.HomesteadSigner{} 2399 testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 2400 testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) 2401 bankFunds = big.NewInt(100000000000000000) 2402 gspec = Genesis{ 2403 Config: params.TestChainConfig, 2404 Alloc: GenesisAlloc{ 2405 testBankAddress: {Balance: bankFunds}, 2406 common.HexToAddress("0xc0de"): { 2407 Code: []byte{0x60, 0x01, 0x50}, 2408 Balance: big.NewInt(0), 2409 }, // push 1, pop 2410 }, 2411 GasLimit: 100e6, // 100 M 2412 } 2413 ) 2414 // Generate the original common chain segment and the two competing forks 2415 engine := ethash.NewFaker() 2416 db := rawdb.NewMemoryDatabase() 2417 genesis := gspec.MustCommit(db) 2418 2419 blockGenerator := func(i int, block *BlockGen) { 2420 block.SetCoinbase(common.Address{1}) 2421 for txi := 0; txi < numTxs; txi++ { 2422 uniq := uint64(i*numTxs + txi) 2423 recipient := recipientFn(uniq) 2424 tx, err := types.SignTx(types.NewTransaction(uniq, recipient, big.NewInt(1), params.TxGas, big.NewInt(1), nil), signer, testBankKey) 2425 if err != nil { 2426 b.Error(err) 2427 } 2428 block.AddTx(tx) 2429 } 2430 } 2431 2432 shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, numBlocks, blockGenerator) 2433 b.StopTimer() 2434 b.ResetTimer() 2435 for i := 0; i < b.N; i++ { 2436 // Import the shared chain and the original canonical one 2437 diskdb := rawdb.NewMemoryDatabase() 2438 gspec.MustCommit(diskdb) 2439 2440 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) 2441 if err != nil { 2442 b.Fatalf("failed to create tester chain: %v", err) 2443 } 2444 b.StartTimer() 2445 if _, err := chain.InsertChain(shared); err != nil { 2446 b.Fatalf("failed to insert shared chain: %v", err) 2447 } 2448 b.StopTimer() 2449 if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks { 2450 b.Fatalf("Transactions were not included, expected %d, got %d", numTxs*numBlocks, got) 2451 2452 } 2453 } 2454 } 2455 2456 func BenchmarkBlockChain_1x1000ValueTransferToNonexisting(b *testing.B) { 2457 var ( 2458 numTxs = 1000 2459 numBlocks = 1 2460 ) 2461 recipientFn := func(nonce uint64) common.Address { 2462 return common.BigToAddress(big.NewInt(0).SetUint64(1337 + nonce)) 2463 } 2464 dataFn := func(nonce uint64) []byte { 2465 return nil 2466 } 2467 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 2468 } 2469 2470 func BenchmarkBlockChain_1x1000ValueTransferToExisting(b *testing.B) { 2471 var ( 2472 numTxs = 1000 2473 numBlocks = 1 2474 ) 2475 b.StopTimer() 2476 b.ResetTimer() 2477 2478 recipientFn := func(nonce uint64) common.Address { 2479 return common.BigToAddress(big.NewInt(0).SetUint64(1337)) 2480 } 2481 dataFn := func(nonce uint64) []byte { 2482 return nil 2483 } 2484 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 2485 } 2486 2487 func BenchmarkBlockChain_1x1000Executions(b *testing.B) { 2488 var ( 2489 numTxs = 1000 2490 numBlocks = 1 2491 ) 2492 b.StopTimer() 2493 b.ResetTimer() 2494 2495 recipientFn := func(nonce uint64) common.Address { 2496 return common.BigToAddress(big.NewInt(0).SetUint64(0xc0de)) 2497 } 2498 dataFn := func(nonce uint64) []byte { 2499 return nil 2500 } 2501 benchmarkLargeNumberOfValueToNonexisting(b, numTxs, numBlocks, recipientFn, dataFn) 2502 } 2503 2504 // Tests that importing a some old blocks, where all blocks are before the 2505 // pruning point. 2506 // This internally leads to a sidechain import, since the blocks trigger an 2507 // ErrPrunedAncestor error. 2508 // This may e.g. happen if 2509 // 1. Downloader rollbacks a batch of inserted blocks and exits 2510 // 2. Downloader starts to sync again 2511 // 3. The blocks fetched are all known and canonical blocks 2512 func TestSideImportPrunedBlocks(t *testing.T) { 2513 // Generate a canonical chain to act as the main dataset 2514 engine := ethash.NewFaker() 2515 db := rawdb.NewMemoryDatabase() 2516 genesis := new(Genesis).MustCommit(db) 2517 2518 // Generate and import the canonical chain 2519 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TestTriesInMemory, nil) 2520 diskdb := rawdb.NewMemoryDatabase() 2521 new(Genesis).MustCommit(diskdb) 2522 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) 2523 if err != nil { 2524 t.Fatalf("failed to create tester chain: %v", err) 2525 } 2526 if n, err := chain.InsertChain(blocks); err != nil { 2527 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2528 } 2529 2530 lastPrunedIndex := len(blocks) - TestTriesInMemory - 1 2531 lastPrunedBlock := blocks[lastPrunedIndex-1] 2532 2533 // Verify pruning of lastPrunedBlock 2534 if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) { 2535 t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64()) 2536 } 2537 firstNonPrunedBlock := blocks[len(blocks)-TestTriesInMemory] 2538 // Verify firstNonPrunedBlock is not pruned 2539 if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) { 2540 t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64()) 2541 } 2542 // Now re-import some old blocks 2543 blockToReimport := blocks[5:8] 2544 _, err = chain.InsertChain(blockToReimport) 2545 if err != nil { 2546 t.Errorf("Got error, %v", err) 2547 } 2548 } 2549 2550 // TestDeleteCreateRevert tests a weird state transition corner case that we hit 2551 // while changing the internals of statedb. The workflow is that a contract is 2552 // self destructed, then in a followup transaction (but same block) it's created 2553 // again and the transaction reverted. 2554 // 2555 // The original statedb implementation flushed dirty objects to the tries after 2556 // each transaction, so this works ok. The rework accumulated writes in memory 2557 // first, but the journal wiped the entire state object on create-revert. 2558 func TestDeleteCreateRevert(t *testing.T) { 2559 var ( 2560 aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") 2561 bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb") 2562 // Generate a canonical chain to act as the main dataset 2563 engine = ethash.NewFaker() 2564 db = rawdb.NewMemoryDatabase() 2565 2566 // A sender who makes transactions, has some funds 2567 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 2568 address = crypto.PubkeyToAddress(key.PublicKey) 2569 funds = big.NewInt(1000000000) 2570 gspec = &Genesis{ 2571 Config: params.TestChainConfig, 2572 Alloc: GenesisAlloc{ 2573 address: {Balance: funds}, 2574 // The address 0xAAAAA selfdestructs if called 2575 aa: { 2576 // Code needs to just selfdestruct 2577 Code: []byte{byte(vm.PC), byte(vm.SELFDESTRUCT)}, 2578 Nonce: 1, 2579 Balance: big.NewInt(0), 2580 }, 2581 // The address 0xBBBB send 1 wei to 0xAAAA, then reverts 2582 bb: { 2583 Code: []byte{ 2584 byte(vm.PC), // [0] 2585 byte(vm.DUP1), // [0,0] 2586 byte(vm.DUP1), // [0,0,0] 2587 byte(vm.DUP1), // [0,0,0,0] 2588 byte(vm.PUSH1), 0x01, // [0,0,0,0,1] (value) 2589 byte(vm.PUSH2), 0xaa, 0xaa, // [0,0,0,0,1, 0xaaaa] 2590 byte(vm.GAS), 2591 byte(vm.CALL), 2592 byte(vm.REVERT), 2593 }, 2594 Balance: big.NewInt(1), 2595 }, 2596 }, 2597 } 2598 genesis = gspec.MustCommit(db) 2599 ) 2600 2601 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 1, func(i int, b *BlockGen) { 2602 b.SetCoinbase(common.Address{1}) 2603 // One transaction to AAAA 2604 tx, _ := types.SignTx(types.NewTransaction(0, aa, 2605 big.NewInt(0), 50000, big.NewInt(1), nil), types.HomesteadSigner{}, key) 2606 b.AddTx(tx) 2607 // One transaction to BBBB 2608 tx, _ = types.SignTx(types.NewTransaction(1, bb, 2609 big.NewInt(0), 100000, big.NewInt(1), nil), types.HomesteadSigner{}, key) 2610 b.AddTx(tx) 2611 }) 2612 // Import the canonical chain 2613 diskdb := rawdb.NewMemoryDatabase() 2614 gspec.MustCommit(diskdb) 2615 2616 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) 2617 if err != nil { 2618 t.Fatalf("failed to create tester chain: %v", err) 2619 } 2620 if n, err := chain.InsertChain(blocks); err != nil { 2621 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2622 } 2623 } 2624 2625 // TestDeleteRecreateSlots tests a state-transition that contains both deletion 2626 // and recreation of contract state. 2627 // Contract A exists, has slots 1 and 2 set 2628 // Tx 1: Selfdestruct A 2629 // Tx 2: Re-create A, set slots 3 and 4 2630 // Expected outcome is that _all_ slots are cleared from A, due to the selfdestruct, 2631 // and then the new slots exist 2632 func TestDeleteRecreateSlots(t *testing.T) { 2633 var ( 2634 // Generate a canonical chain to act as the main dataset 2635 engine = ethash.NewFaker() 2636 db = rawdb.NewMemoryDatabase() 2637 // A sender who makes transactions, has some funds 2638 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 2639 address = crypto.PubkeyToAddress(key.PublicKey) 2640 funds = big.NewInt(1000000000) 2641 bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb") 2642 aaStorage = make(map[common.Hash]common.Hash) // Initial storage in AA 2643 aaCode = []byte{byte(vm.PC), byte(vm.SELFDESTRUCT)} // Code for AA (simple selfdestruct) 2644 ) 2645 // Populate two slots 2646 aaStorage[common.HexToHash("01")] = common.HexToHash("01") 2647 aaStorage[common.HexToHash("02")] = common.HexToHash("02") 2648 2649 // The bb-code needs to CREATE2 the aa contract. It consists of 2650 // both initcode and deployment code 2651 // initcode: 2652 // 1. Set slots 3=3, 4=4, 2653 // 2. Return aaCode 2654 2655 initCode := []byte{ 2656 byte(vm.PUSH1), 0x3, // value 2657 byte(vm.PUSH1), 0x3, // location 2658 byte(vm.SSTORE), // Set slot[3] = 1 2659 byte(vm.PUSH1), 0x4, // value 2660 byte(vm.PUSH1), 0x4, // location 2661 byte(vm.SSTORE), // Set slot[4] = 1 2662 // Slots are set, now return the code 2663 byte(vm.PUSH2), byte(vm.PC), byte(vm.SELFDESTRUCT), // Push code on stack 2664 byte(vm.PUSH1), 0x0, // memory start on stack 2665 byte(vm.MSTORE), 2666 // Code is now in memory. 2667 byte(vm.PUSH1), 0x2, // size 2668 byte(vm.PUSH1), byte(32 - 2), // offset 2669 byte(vm.RETURN), 2670 } 2671 if l := len(initCode); l > 32 { 2672 t.Fatalf("init code is too long for a pushx, need a more elaborate deployer") 2673 } 2674 bbCode := []byte{ 2675 // Push initcode onto stack 2676 byte(vm.PUSH1) + byte(len(initCode)-1)} 2677 bbCode = append(bbCode, initCode...) 2678 bbCode = append(bbCode, []byte{ 2679 byte(vm.PUSH1), 0x0, // memory start on stack 2680 byte(vm.MSTORE), 2681 byte(vm.PUSH1), 0x00, // salt 2682 byte(vm.PUSH1), byte(len(initCode)), // size 2683 byte(vm.PUSH1), byte(32 - len(initCode)), // offset 2684 byte(vm.PUSH1), 0x00, // endowment 2685 byte(vm.CREATE2), 2686 }...) 2687 2688 initHash := crypto.Keccak256Hash(initCode) 2689 aa := crypto.CreateAddress2(bb, [32]byte{}, initHash[:]) 2690 t.Logf("Destination address: %x\n", aa) 2691 2692 gspec := &Genesis{ 2693 Config: params.TestChainConfig, 2694 Alloc: GenesisAlloc{ 2695 address: {Balance: funds}, 2696 // The address 0xAAAAA selfdestructs if called 2697 aa: { 2698 // Code needs to just selfdestruct 2699 Code: aaCode, 2700 Nonce: 1, 2701 Balance: big.NewInt(0), 2702 Storage: aaStorage, 2703 }, 2704 // The contract BB recreates AA 2705 bb: { 2706 Code: bbCode, 2707 Balance: big.NewInt(1), 2708 }, 2709 }, 2710 } 2711 genesis := gspec.MustCommit(db) 2712 2713 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 1, func(i int, b *BlockGen) { 2714 b.SetCoinbase(common.Address{1}) 2715 // One transaction to AA, to kill it 2716 tx, _ := types.SignTx(types.NewTransaction(0, aa, 2717 big.NewInt(0), 50000, big.NewInt(1), nil), types.HomesteadSigner{}, key) 2718 b.AddTx(tx) 2719 // One transaction to BB, to recreate AA 2720 tx, _ = types.SignTx(types.NewTransaction(1, bb, 2721 big.NewInt(0), 100000, big.NewInt(1), nil), types.HomesteadSigner{}, key) 2722 b.AddTx(tx) 2723 }) 2724 // Import the canonical chain 2725 diskdb := rawdb.NewMemoryDatabase() 2726 gspec.MustCommit(diskdb) 2727 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{ 2728 Debug: true, 2729 Tracer: vm.NewJSONLogger(nil, os.Stdout), 2730 }, nil, nil) 2731 if err != nil { 2732 t.Fatalf("failed to create tester chain: %v", err) 2733 } 2734 if n, err := chain.InsertChain(blocks); err != nil { 2735 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2736 } 2737 statedb, _ := chain.State() 2738 2739 // If all is correct, then slot 1 and 2 are zero 2740 if got, exp := statedb.GetState(aa, common.HexToHash("01")), (common.Hash{}); got != exp { 2741 t.Errorf("got %x exp %x", got, exp) 2742 } 2743 if got, exp := statedb.GetState(aa, common.HexToHash("02")), (common.Hash{}); got != exp { 2744 t.Errorf("got %x exp %x", got, exp) 2745 } 2746 // Also, 3 and 4 should be set 2747 if got, exp := statedb.GetState(aa, common.HexToHash("03")), common.HexToHash("03"); got != exp { 2748 t.Fatalf("got %x exp %x", got, exp) 2749 } 2750 if got, exp := statedb.GetState(aa, common.HexToHash("04")), common.HexToHash("04"); got != exp { 2751 t.Fatalf("got %x exp %x", got, exp) 2752 } 2753 } 2754 2755 // TestDeleteRecreateAccount tests a state-transition that contains deletion of a 2756 // contract with storage, and a recreate of the same contract via a 2757 // regular value-transfer 2758 // Expected outcome is that _all_ slots are cleared from A 2759 func TestDeleteRecreateAccount(t *testing.T) { 2760 var ( 2761 // Generate a canonical chain to act as the main dataset 2762 engine = ethash.NewFaker() 2763 db = rawdb.NewMemoryDatabase() 2764 // A sender who makes transactions, has some funds 2765 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 2766 address = crypto.PubkeyToAddress(key.PublicKey) 2767 funds = big.NewInt(1000000000) 2768 2769 aa = common.HexToAddress("0x7217d81b76bdd8707601e959454e3d776aee5f43") 2770 aaStorage = make(map[common.Hash]common.Hash) // Initial storage in AA 2771 aaCode = []byte{byte(vm.PC), byte(vm.SELFDESTRUCT)} // Code for AA (simple selfdestruct) 2772 ) 2773 // Populate two slots 2774 aaStorage[common.HexToHash("01")] = common.HexToHash("01") 2775 aaStorage[common.HexToHash("02")] = common.HexToHash("02") 2776 2777 gspec := &Genesis{ 2778 Config: params.TestChainConfig, 2779 Alloc: GenesisAlloc{ 2780 address: {Balance: funds}, 2781 // The address 0xAAAAA selfdestructs if called 2782 aa: { 2783 // Code needs to just selfdestruct 2784 Code: aaCode, 2785 Nonce: 1, 2786 Balance: big.NewInt(0), 2787 Storage: aaStorage, 2788 }, 2789 }, 2790 } 2791 genesis := gspec.MustCommit(db) 2792 2793 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 1, func(i int, b *BlockGen) { 2794 b.SetCoinbase(common.Address{1}) 2795 // One transaction to AA, to kill it 2796 tx, _ := types.SignTx(types.NewTransaction(0, aa, 2797 big.NewInt(0), 50000, big.NewInt(1), nil), types.HomesteadSigner{}, key) 2798 b.AddTx(tx) 2799 // One transaction to AA, to recreate it (but without storage 2800 tx, _ = types.SignTx(types.NewTransaction(1, aa, 2801 big.NewInt(1), 100000, big.NewInt(1), nil), types.HomesteadSigner{}, key) 2802 b.AddTx(tx) 2803 }) 2804 // Import the canonical chain 2805 diskdb := rawdb.NewMemoryDatabase() 2806 gspec.MustCommit(diskdb) 2807 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{ 2808 Debug: true, 2809 Tracer: vm.NewJSONLogger(nil, os.Stdout), 2810 }, nil, nil) 2811 if err != nil { 2812 t.Fatalf("failed to create tester chain: %v", err) 2813 } 2814 if n, err := chain.InsertChain(blocks); err != nil { 2815 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2816 } 2817 statedb, _ := chain.State() 2818 2819 // If all is correct, then both slots are zero 2820 if got, exp := statedb.GetState(aa, common.HexToHash("01")), (common.Hash{}); got != exp { 2821 t.Errorf("got %x exp %x", got, exp) 2822 } 2823 if got, exp := statedb.GetState(aa, common.HexToHash("02")), (common.Hash{}); got != exp { 2824 t.Errorf("got %x exp %x", got, exp) 2825 } 2826 } 2827 2828 // TestDeleteRecreateSlotsAcrossManyBlocks tests multiple state-transition that contains both deletion 2829 // and recreation of contract state. 2830 // Contract A exists, has slots 1 and 2 set 2831 // Tx 1: Selfdestruct A 2832 // Tx 2: Re-create A, set slots 3 and 4 2833 // Expected outcome is that _all_ slots are cleared from A, due to the selfdestruct, 2834 // and then the new slots exist 2835 func TestDeleteRecreateSlotsAcrossManyBlocks(t *testing.T) { 2836 var ( 2837 // Generate a canonical chain to act as the main dataset 2838 engine = ethash.NewFaker() 2839 db = rawdb.NewMemoryDatabase() 2840 // A sender who makes transactions, has some funds 2841 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 2842 address = crypto.PubkeyToAddress(key.PublicKey) 2843 funds = big.NewInt(1000000000) 2844 bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb") 2845 aaStorage = make(map[common.Hash]common.Hash) // Initial storage in AA 2846 aaCode = []byte{byte(vm.PC), byte(vm.SELFDESTRUCT)} // Code for AA (simple selfdestruct) 2847 ) 2848 // Populate two slots 2849 aaStorage[common.HexToHash("01")] = common.HexToHash("01") 2850 aaStorage[common.HexToHash("02")] = common.HexToHash("02") 2851 2852 // The bb-code needs to CREATE2 the aa contract. It consists of 2853 // both initcode and deployment code 2854 // initcode: 2855 // 1. Set slots 3=blocknum+1, 4=4, 2856 // 2. Return aaCode 2857 2858 initCode := []byte{ 2859 byte(vm.PUSH1), 0x1, // 2860 byte(vm.NUMBER), // value = number + 1 2861 byte(vm.ADD), // 2862 byte(vm.PUSH1), 0x3, // location 2863 byte(vm.SSTORE), // Set slot[3] = number + 1 2864 byte(vm.PUSH1), 0x4, // value 2865 byte(vm.PUSH1), 0x4, // location 2866 byte(vm.SSTORE), // Set slot[4] = 4 2867 // Slots are set, now return the code 2868 byte(vm.PUSH2), byte(vm.PC), byte(vm.SELFDESTRUCT), // Push code on stack 2869 byte(vm.PUSH1), 0x0, // memory start on stack 2870 byte(vm.MSTORE), 2871 // Code is now in memory. 2872 byte(vm.PUSH1), 0x2, // size 2873 byte(vm.PUSH1), byte(32 - 2), // offset 2874 byte(vm.RETURN), 2875 } 2876 if l := len(initCode); l > 32 { 2877 t.Fatalf("init code is too long for a pushx, need a more elaborate deployer") 2878 } 2879 bbCode := []byte{ 2880 // Push initcode onto stack 2881 byte(vm.PUSH1) + byte(len(initCode)-1)} 2882 bbCode = append(bbCode, initCode...) 2883 bbCode = append(bbCode, []byte{ 2884 byte(vm.PUSH1), 0x0, // memory start on stack 2885 byte(vm.MSTORE), 2886 byte(vm.PUSH1), 0x00, // salt 2887 byte(vm.PUSH1), byte(len(initCode)), // size 2888 byte(vm.PUSH1), byte(32 - len(initCode)), // offset 2889 byte(vm.PUSH1), 0x00, // endowment 2890 byte(vm.CREATE2), 2891 }...) 2892 2893 initHash := crypto.Keccak256Hash(initCode) 2894 aa := crypto.CreateAddress2(bb, [32]byte{}, initHash[:]) 2895 t.Logf("Destination address: %x\n", aa) 2896 gspec := &Genesis{ 2897 Config: params.TestChainConfig, 2898 Alloc: GenesisAlloc{ 2899 address: {Balance: funds}, 2900 // The address 0xAAAAA selfdestructs if called 2901 aa: { 2902 // Code needs to just selfdestruct 2903 Code: aaCode, 2904 Nonce: 1, 2905 Balance: big.NewInt(0), 2906 Storage: aaStorage, 2907 }, 2908 // The contract BB recreates AA 2909 bb: { 2910 Code: bbCode, 2911 Balance: big.NewInt(1), 2912 }, 2913 }, 2914 } 2915 genesis := gspec.MustCommit(db) 2916 var nonce uint64 2917 2918 type expectation struct { 2919 exist bool 2920 blocknum int 2921 values map[int]int 2922 } 2923 var current = &expectation{ 2924 exist: true, // exists in genesis 2925 blocknum: 0, 2926 values: map[int]int{1: 1, 2: 2}, 2927 } 2928 var expectations []*expectation 2929 var newDestruct = func(e *expectation) *types.Transaction { 2930 tx, _ := types.SignTx(types.NewTransaction(nonce, aa, 2931 big.NewInt(0), 50000, big.NewInt(1), nil), types.HomesteadSigner{}, key) 2932 nonce++ 2933 if e.exist { 2934 e.exist = false 2935 e.values = nil 2936 } 2937 t.Logf("block %d; adding destruct\n", e.blocknum) 2938 return tx 2939 } 2940 var newResurrect = func(e *expectation) *types.Transaction { 2941 tx, _ := types.SignTx(types.NewTransaction(nonce, bb, 2942 big.NewInt(0), 100000, big.NewInt(1), nil), types.HomesteadSigner{}, key) 2943 nonce++ 2944 if !e.exist { 2945 e.exist = true 2946 e.values = map[int]int{3: e.blocknum + 1, 4: 4} 2947 } 2948 t.Logf("block %d; adding resurrect\n", e.blocknum) 2949 return tx 2950 } 2951 2952 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 150, func(i int, b *BlockGen) { 2953 var exp = new(expectation) 2954 exp.blocknum = i + 1 2955 exp.values = make(map[int]int) 2956 for k, v := range current.values { 2957 exp.values[k] = v 2958 } 2959 exp.exist = current.exist 2960 2961 b.SetCoinbase(common.Address{1}) 2962 if i%2 == 0 { 2963 b.AddTx(newDestruct(exp)) 2964 } 2965 if i%3 == 0 { 2966 b.AddTx(newResurrect(exp)) 2967 } 2968 if i%5 == 0 { 2969 b.AddTx(newDestruct(exp)) 2970 } 2971 if i%7 == 0 { 2972 b.AddTx(newResurrect(exp)) 2973 } 2974 expectations = append(expectations, exp) 2975 current = exp 2976 }) 2977 // Import the canonical chain 2978 diskdb := rawdb.NewMemoryDatabase() 2979 gspec.MustCommit(diskdb) 2980 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{ 2981 //Debug: true, 2982 //Tracer: vm.NewJSONLogger(nil, os.Stdout), 2983 }, nil, nil) 2984 if err != nil { 2985 t.Fatalf("failed to create tester chain: %v", err) 2986 } 2987 var asHash = func(num int) common.Hash { 2988 return common.BytesToHash([]byte{byte(num)}) 2989 } 2990 for i, block := range blocks { 2991 blockNum := i + 1 2992 if n, err := chain.InsertChain([]*types.Block{block}); err != nil { 2993 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 2994 } 2995 statedb, _ := chain.State() 2996 // If all is correct, then slot 1 and 2 are zero 2997 if got, exp := statedb.GetState(aa, common.HexToHash("01")), (common.Hash{}); got != exp { 2998 t.Errorf("block %d, got %x exp %x", blockNum, got, exp) 2999 } 3000 if got, exp := statedb.GetState(aa, common.HexToHash("02")), (common.Hash{}); got != exp { 3001 t.Errorf("block %d, got %x exp %x", blockNum, got, exp) 3002 } 3003 exp := expectations[i] 3004 if exp.exist { 3005 if !statedb.Exist(aa) { 3006 t.Fatalf("block %d, expected %v to exist, it did not", blockNum, aa) 3007 } 3008 for slot, val := range exp.values { 3009 if gotValue, expValue := statedb.GetState(aa, asHash(slot)), asHash(val); gotValue != expValue { 3010 t.Fatalf("block %d, slot %d, got %x exp %x", blockNum, slot, gotValue, expValue) 3011 } 3012 } 3013 } else { 3014 if statedb.Exist(aa) { 3015 t.Fatalf("block %d, expected %v to not exist, it did", blockNum, aa) 3016 } 3017 } 3018 } 3019 } 3020 3021 // TestInitThenFailCreateContract tests a pretty notorious case that happened 3022 // on mainnet over blocks 7338108, 7338110 and 7338115. 3023 // - Block 7338108: address e771789f5cccac282f23bb7add5690e1f6ca467c is initiated 3024 // with 0.001 ether (thus created but no code) 3025 // - Block 7338110: a CREATE2 is attempted. The CREATE2 would deploy code on 3026 // the same address e771789f5cccac282f23bb7add5690e1f6ca467c. However, the 3027 // deployment fails due to OOG during initcode execution 3028 // - Block 7338115: another tx checks the balance of 3029 // e771789f5cccac282f23bb7add5690e1f6ca467c, and the snapshotter returned it as 3030 // zero. 3031 // 3032 // The problem being that the snapshotter maintains a destructset, and adds items 3033 // to the destructset in case something is created "onto" an existing item. 3034 // We need to either roll back the snapDestructs, or not place it into snapDestructs 3035 // in the first place. 3036 // 3037 func TestInitThenFailCreateContract(t *testing.T) { 3038 var ( 3039 // Generate a canonical chain to act as the main dataset 3040 engine = ethash.NewFaker() 3041 db = rawdb.NewMemoryDatabase() 3042 // A sender who makes transactions, has some funds 3043 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 3044 address = crypto.PubkeyToAddress(key.PublicKey) 3045 funds = big.NewInt(1000000000) 3046 bb = common.HexToAddress("0x000000000000000000000000000000000000bbbb") 3047 ) 3048 3049 // The bb-code needs to CREATE2 the aa contract. It consists of 3050 // both initcode and deployment code 3051 // initcode: 3052 // 1. If blocknum < 1, error out (e.g invalid opcode) 3053 // 2. else, return a snippet of code 3054 initCode := []byte{ 3055 byte(vm.PUSH1), 0x1, // y (2) 3056 byte(vm.NUMBER), // x (number) 3057 byte(vm.GT), // x > y? 3058 byte(vm.PUSH1), byte(0x8), 3059 byte(vm.JUMPI), // jump to label if number > 2 3060 byte(0xFE), // illegal opcode 3061 byte(vm.JUMPDEST), 3062 byte(vm.PUSH1), 0x2, // size 3063 byte(vm.PUSH1), 0x0, // offset 3064 byte(vm.RETURN), // return 2 bytes of zero-code 3065 } 3066 if l := len(initCode); l > 32 { 3067 t.Fatalf("init code is too long for a pushx, need a more elaborate deployer") 3068 } 3069 bbCode := []byte{ 3070 // Push initcode onto stack 3071 byte(vm.PUSH1) + byte(len(initCode)-1)} 3072 bbCode = append(bbCode, initCode...) 3073 bbCode = append(bbCode, []byte{ 3074 byte(vm.PUSH1), 0x0, // memory start on stack 3075 byte(vm.MSTORE), 3076 byte(vm.PUSH1), 0x00, // salt 3077 byte(vm.PUSH1), byte(len(initCode)), // size 3078 byte(vm.PUSH1), byte(32 - len(initCode)), // offset 3079 byte(vm.PUSH1), 0x00, // endowment 3080 byte(vm.CREATE2), 3081 }...) 3082 3083 initHash := crypto.Keccak256Hash(initCode) 3084 aa := crypto.CreateAddress2(bb, [32]byte{}, initHash[:]) 3085 t.Logf("Destination address: %x\n", aa) 3086 3087 gspec := &Genesis{ 3088 Config: params.TestChainConfig, 3089 Alloc: GenesisAlloc{ 3090 address: {Balance: funds}, 3091 // The address aa has some funds 3092 aa: {Balance: big.NewInt(100000)}, 3093 // The contract BB tries to create code onto AA 3094 bb: { 3095 Code: bbCode, 3096 Balance: big.NewInt(1), 3097 }, 3098 }, 3099 } 3100 genesis := gspec.MustCommit(db) 3101 nonce := uint64(0) 3102 blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 4, func(i int, b *BlockGen) { 3103 b.SetCoinbase(common.Address{1}) 3104 // One transaction to BB 3105 tx, _ := types.SignTx(types.NewTransaction(nonce, bb, 3106 big.NewInt(0), 100000, big.NewInt(1), nil), types.HomesteadSigner{}, key) 3107 b.AddTx(tx) 3108 nonce++ 3109 }) 3110 3111 // Import the canonical chain 3112 diskdb := rawdb.NewMemoryDatabase() 3113 gspec.MustCommit(diskdb) 3114 chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{ 3115 //Debug: true, 3116 //Tracer: vm.NewJSONLogger(nil, os.Stdout), 3117 }, nil, nil) 3118 if err != nil { 3119 t.Fatalf("failed to create tester chain: %v", err) 3120 } 3121 statedb, _ := chain.State() 3122 if got, exp := statedb.GetBalance(aa), big.NewInt(100000); got.Cmp(exp) != 0 { 3123 t.Fatalf("Genesis err, got %v exp %v", got, exp) 3124 } 3125 // First block tries to create, but fails 3126 { 3127 block := blocks[0] 3128 if _, err := chain.InsertChain([]*types.Block{blocks[0]}); err != nil { 3129 t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err) 3130 } 3131 statedb, _ = chain.State() 3132 if got, exp := statedb.GetBalance(aa), big.NewInt(100000); got.Cmp(exp) != 0 { 3133 t.Fatalf("block %d: got %v exp %v", block.NumberU64(), got, exp) 3134 } 3135 } 3136 // Import the rest of the blocks 3137 for _, block := range blocks[1:] { 3138 if _, err := chain.InsertChain([]*types.Block{block}); err != nil { 3139 t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err) 3140 } 3141 } 3142 } 3143 3144 // TestEIP2718Transition tests that an EIP-2718 transaction will be accepted 3145 // after the fork block has passed. This is verified by sending an EIP-2930 3146 // access list transaction, which specifies a single slot access, and then 3147 // checking that the gas usage of a hot SLOAD and a cold SLOAD are calculated 3148 // correctly. 3149 func TestEIP2718Transition(t *testing.T) { 3150 var ( 3151 aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa") 3152 3153 // Generate a canonical chain to act as the main dataset 3154 engine = ethash.NewFaker() 3155 db = rawdb.NewMemoryDatabase() 3156 3157 // A sender who makes transactions, has some funds 3158 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 3159 address = crypto.PubkeyToAddress(key.PublicKey) 3160 funds = big.NewInt(1000000000) 3161 gspec = &Genesis{ 3162 Config: params.YoloV3ChainConfig, 3163 Alloc: GenesisAlloc{ 3164 address: {Balance: funds}, 3165 // The address 0xAAAA sloads 0x00 and 0x01 3166 aa: { 3167 Code: []byte{ 3168 byte(vm.PC), 3169 byte(vm.PC), 3170 byte(vm.SLOAD), 3171 byte(vm.SLOAD), 3172 }, 3173 Nonce: 0, 3174 Balance: big.NewInt(0), 3175 }, 3176 }, 3177 } 3178 genesis = gspec.MustCommit(db) 3179 ) 3180 3181 blocks, _ := GenerateChain(gspec.Config, genesis, engine, db, 1, func(i int, b *BlockGen) { 3182 b.SetCoinbase(common.Address{1}) 3183 3184 // One transaction to 0xAAAA 3185 signer := types.LatestSigner(gspec.Config) 3186 tx, _ := types.SignNewTx(key, signer, &types.AccessListTx{ 3187 ChainID: gspec.Config.ChainID, 3188 Nonce: 0, 3189 To: &aa, 3190 Gas: 30000, 3191 GasPrice: big.NewInt(1), 3192 AccessList: types.AccessList{{ 3193 Address: aa, 3194 StorageKeys: []common.Hash{{0}}, 3195 }}, 3196 }) 3197 b.AddTx(tx) 3198 }) 3199 3200 // Import the canonical chain 3201 diskdb := rawdb.NewMemoryDatabase() 3202 gspec.MustCommit(diskdb) 3203 3204 chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil) 3205 if err != nil { 3206 t.Fatalf("failed to create tester chain: %v", err) 3207 } 3208 if n, err := chain.InsertChain(blocks); err != nil { 3209 t.Fatalf("block %d: failed to insert into chain: %v", n, err) 3210 } 3211 3212 block := chain.GetBlockByNumber(1) 3213 3214 // Expected gas is intrinsic + 2 * pc + hot load + cold load, since only one load is in the access list 3215 expected := params.TxGas + params.TxAccessListAddressGas + params.TxAccessListStorageKeyGas + vm.GasQuickStep*2 + vm.WarmStorageReadCostEIP2929 + vm.ColdSloadCostEIP2929 3216 if block.GasUsed() != expected { 3217 t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expected, block.GasUsed()) 3218 3219 } 3220 }