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