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