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