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