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