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