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