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