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