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