github.com/MetalBlockchain/subnet-evm@v0.4.9/core/test_blockchain.go (about) 1 // (c) 2020-2021, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package core 5 6 import ( 7 "fmt" 8 "math/big" 9 "strings" 10 "testing" 11 12 "github.com/MetalBlockchain/subnet-evm/commontype" 13 "github.com/MetalBlockchain/subnet-evm/consensus/dummy" 14 "github.com/MetalBlockchain/subnet-evm/core/rawdb" 15 "github.com/MetalBlockchain/subnet-evm/core/state" 16 "github.com/MetalBlockchain/subnet-evm/core/types" 17 "github.com/MetalBlockchain/subnet-evm/ethdb" 18 "github.com/MetalBlockchain/subnet-evm/params" 19 "github.com/MetalBlockchain/subnet-evm/precompile" 20 "github.com/ethereum/go-ethereum/common" 21 "github.com/ethereum/go-ethereum/crypto" 22 "github.com/stretchr/testify/assert" 23 ) 24 25 type ChainTest struct { 26 Name string 27 testFunc func( 28 t *testing.T, 29 create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error), 30 ) 31 } 32 33 var tests = []ChainTest{ 34 { 35 "InsertChainAcceptSingleBlock", 36 TestInsertChainAcceptSingleBlock, 37 }, 38 { 39 "InsertForkedChain", 40 TestInsertLongForkedChain, 41 }, 42 { 43 "AcceptNonCanonicalBlock", 44 TestAcceptNonCanonicalBlock, 45 }, 46 { 47 "SetPreferenceRewind", 48 TestSetPreferenceRewind, 49 }, 50 { 51 "BuildOnVariousStages", 52 TestBuildOnVariousStages, 53 }, 54 { 55 "EmptyBlocks", 56 TestEmptyBlocks, 57 }, 58 { 59 "AcceptBlockIdenticalStateRoot", 60 TestAcceptBlockIdenticalStateRoot, 61 }, 62 { 63 "ReprocessAcceptBlockIdenticalStateRoot", 64 TestReprocessAcceptBlockIdenticalStateRoot, 65 }, 66 { 67 "GenerateChainInvalidBlockFee", 68 TestGenerateChainInvalidBlockFee, 69 }, 70 { 71 "InsertChainInvalidBlockFee", 72 TestInsertChainInvalidBlockFee, 73 }, 74 { 75 "InsertChainValidBlockFee", 76 TestInsertChainValidBlockFee, 77 }, 78 { 79 "TestStatefulPrecompiles", 80 TestStatefulPrecompiles, 81 }, 82 } 83 84 func copyMemDB(db ethdb.Database) (ethdb.Database, error) { 85 newDB := rawdb.NewMemoryDatabase() 86 iter := db.NewIterator(nil, nil) 87 defer iter.Release() 88 for iter.Next() { 89 if err := newDB.Put(iter.Key(), iter.Value()); err != nil { 90 return nil, err 91 } 92 } 93 94 return newDB, nil 95 } 96 97 // checkBlockChainState creates a new BlockChain instance and checks that exporting each block from 98 // genesis to last accepted from the original instance yields the same last accepted block and state 99 // root. 100 // Additionally, create another BlockChain instance from [originalDB] to ensure that BlockChain is 101 // persisted correctly through a restart. 102 func checkBlockChainState( 103 t *testing.T, 104 bc *BlockChain, 105 genesis *Genesis, 106 originalDB ethdb.Database, 107 create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error), 108 checkState func(sdb *state.StateDB) error, 109 ) (*BlockChain, *BlockChain, *BlockChain) { 110 var ( 111 chainConfig = bc.Config() 112 lastAcceptedBlock = bc.LastConsensusAcceptedBlock() 113 newDB = rawdb.NewMemoryDatabase() 114 ) 115 116 acceptedState, err := bc.StateAt(lastAcceptedBlock.Root()) 117 if err != nil { 118 t.Fatal(err) 119 } 120 if err := checkState(acceptedState); err != nil { 121 t.Fatalf("Check state failed for original blockchain due to: %s", err) 122 } 123 124 _ = genesis.MustCommit(newDB) 125 126 newBlockChain, err := create(newDB, chainConfig, common.Hash{}) 127 if err != nil { 128 t.Fatalf("Failed to create new blockchain instance: %s", err) 129 } 130 131 for i := uint64(1); i <= lastAcceptedBlock.NumberU64(); i++ { 132 block := bc.GetBlockByNumber(i) 133 if block == nil { 134 t.Fatalf("Failed to retrieve block by number %d from original chain", i) 135 } 136 if err := newBlockChain.InsertBlock(block); err != nil { 137 t.Fatalf("Failed to insert block %s:%d due to %s", block.Hash().Hex(), block.NumberU64(), err) 138 } 139 if err := newBlockChain.Accept(block); err != nil { 140 t.Fatalf("Failed to accept block %s:%d due to %s", block.Hash().Hex(), block.NumberU64(), err) 141 } 142 } 143 newBlockChain.DrainAcceptorQueue() 144 145 newLastAcceptedBlock := newBlockChain.LastConsensusAcceptedBlock() 146 if newLastAcceptedBlock.Hash() != lastAcceptedBlock.Hash() { 147 t.Fatalf("Expected new blockchain to have last accepted block %s:%d, but found %s:%d", lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64(), newLastAcceptedBlock.Hash().Hex(), newLastAcceptedBlock.NumberU64()) 148 } 149 150 // Check that the state of [newBlockChain] passes the check 151 acceptedState, err = newBlockChain.StateAt(lastAcceptedBlock.Root()) 152 if err != nil { 153 t.Fatal(err) 154 } 155 if err := checkState(acceptedState); err != nil { 156 t.Fatalf("Check state failed for newly generated blockchain due to: %s", err) 157 } 158 159 // Copy the database over to prevent any issues when re-using [originalDB] after this call. 160 originalDB, err = copyMemDB(originalDB) 161 if err != nil { 162 t.Fatal(err) 163 } 164 restartedChain, err := create(originalDB, chainConfig, lastAcceptedBlock.Hash()) 165 if err != nil { 166 t.Fatal(err) 167 } 168 defer restartedChain.Stop() 169 if currentBlock := restartedChain.CurrentBlock(); currentBlock.Hash() != lastAcceptedBlock.Hash() { 170 t.Fatalf("Expected restarted chain to have current block %s:%d, but found %s:%d", lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64()) 171 } 172 if restartedLastAcceptedBlock := restartedChain.LastConsensusAcceptedBlock(); restartedLastAcceptedBlock.Hash() != lastAcceptedBlock.Hash() { 173 t.Fatalf("Expected restarted chain to have current block %s:%d, but found %s:%d", lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64(), restartedLastAcceptedBlock.Hash().Hex(), restartedLastAcceptedBlock.NumberU64()) 174 } 175 176 // Check that the state of [restartedChain] passes the check 177 acceptedState, err = restartedChain.StateAt(lastAcceptedBlock.Root()) 178 if err != nil { 179 t.Fatal(err) 180 } 181 if err := checkState(acceptedState); err != nil { 182 t.Fatalf("Check state failed for restarted blockchain due to: %s", err) 183 } 184 185 return bc, newBlockChain, restartedChain 186 } 187 188 func TestInsertChainAcceptSingleBlock(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) { 189 var ( 190 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 191 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 192 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 193 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 194 // We use two separate databases since GenerateChain commits the state roots to its underlying 195 // database. 196 genDB = rawdb.NewMemoryDatabase() 197 chainDB = rawdb.NewMemoryDatabase() 198 ) 199 200 // Ensure that key1 has some funds in the genesis block. 201 genesisBalance := big.NewInt(1000000) 202 gspec := &Genesis{ 203 Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, 204 Alloc: GenesisAlloc{addr1: {Balance: genesisBalance}}, 205 } 206 genesis := gspec.MustCommit(genDB) 207 _ = gspec.MustCommit(chainDB) 208 209 blockchain, err := create(chainDB, gspec.Config, common.Hash{}) 210 if err != nil { 211 t.Fatal(err) 212 } 213 defer blockchain.Stop() 214 215 // This call generates a chain of 3 blocks. 216 signer := types.HomesteadSigner{} 217 // Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing 218 // to the BlockChain's database while generating blocks. 219 chain, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, 10, func(i int, gen *BlockGen) { 220 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1) 221 gen.AddTx(tx) 222 }) 223 if err != nil { 224 t.Fatal(err) 225 } 226 227 // Insert three blocks into the chain and accept only the first block. 228 if _, err := blockchain.InsertChain(chain); err != nil { 229 t.Fatal(err) 230 } 231 if err := blockchain.Accept(chain[0]); err != nil { 232 t.Fatal(err) 233 } 234 blockchain.DrainAcceptorQueue() 235 236 // check the state of the last accepted block 237 checkState := func(sdb *state.StateDB) error { 238 nonce := sdb.GetNonce(addr1) 239 if nonce != 1 { 240 return fmt.Errorf("expected nonce addr1: 1, found nonce: %d", nonce) 241 } 242 transferredFunds := big.NewInt(10000) 243 balance1 := sdb.GetBalance(addr1) 244 expectedBalance1 := new(big.Int).Sub(genesisBalance, transferredFunds) 245 if balance1.Cmp(expectedBalance1) != 0 { 246 return fmt.Errorf("expected addr1 balance: %d, found balance: %d", expectedBalance1, balance1) 247 } 248 249 balance2 := sdb.GetBalance(addr2) 250 expectedBalance2 := transferredFunds 251 if balance2.Cmp(expectedBalance2) != 0 { 252 return fmt.Errorf("expected addr2 balance: %d, found balance: %d", expectedBalance2, balance2) 253 } 254 255 nonce = sdb.GetNonce(addr2) 256 if nonce != 0 { 257 return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce) 258 } 259 return nil 260 } 261 262 checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState) 263 } 264 265 func TestInsertLongForkedChain(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) { 266 var ( 267 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 268 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 269 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 270 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 271 // We use two separate databases since GenerateChain commits the state roots to its underlying 272 // database. 273 genDB = rawdb.NewMemoryDatabase() 274 chainDB = rawdb.NewMemoryDatabase() 275 ) 276 277 // Ensure that key1 has some funds in the genesis block. 278 genesisBalance := big.NewInt(1000000000) 279 gspec := &Genesis{ 280 Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, 281 Alloc: GenesisAlloc{addr1: {Balance: genesisBalance}}, 282 } 283 genesis := gspec.MustCommit(genDB) 284 _ = gspec.MustCommit(chainDB) 285 286 blockchain, err := create(chainDB, gspec.Config, common.Hash{}) 287 if err != nil { 288 t.Fatal(err) 289 } 290 defer blockchain.Stop() 291 292 numBlocks := 129 293 signer := types.HomesteadSigner{} 294 // Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing 295 // to the BlockChain's database while generating blocks. 296 chain1, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, 10, func(i int, gen *BlockGen) { 297 // Generate a transaction to create a unique block 298 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1) 299 gen.AddTx(tx) 300 }) 301 if err != nil { 302 t.Fatal(err) 303 } 304 // Generate the forked chain to be longer than the original chain to check for a regression where 305 // a longer chain can trigger a reorg. 306 chain2, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks+1, 10, func(i int, gen *BlockGen) { 307 // Generate a transaction with a different amount to ensure [chain2] is different than [chain1]. 308 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(5000), params.TxGas, nil, nil), signer, key1) 309 gen.AddTx(tx) 310 }) 311 if err != nil { 312 t.Fatal(err) 313 } 314 315 if blockchain.snaps != nil { 316 if want, got := 1, blockchain.snaps.NumBlockLayers(); got != want { 317 t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want) 318 } 319 } 320 321 // Insert both chains. 322 if _, err := blockchain.InsertChain(chain1); err != nil { 323 t.Fatal(err) 324 } 325 326 if blockchain.snaps != nil { 327 if want, got := 1+len(chain1), blockchain.snaps.NumBlockLayers(); got != want { 328 t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want) 329 } 330 } 331 332 if _, err := blockchain.InsertChain(chain2); err != nil { 333 t.Fatal(err) 334 } 335 336 if blockchain.snaps != nil { 337 if want, got := 1+len(chain1)+len(chain2), blockchain.snaps.NumBlockLayers(); got != want { 338 t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want) 339 } 340 } 341 342 currentBlock := blockchain.CurrentBlock() 343 expectedCurrentBlock := chain1[len(chain1)-1] 344 if currentBlock.Hash() != expectedCurrentBlock.Hash() { 345 t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64()) 346 } 347 348 if err := blockchain.ValidateCanonicalChain(); err != nil { 349 t.Fatal(err) 350 } 351 352 // Accept the first block in [chain1], reject all blocks in [chain2] to 353 // mimic the order that the consensus engine will call Accept/Reject in 354 // and then Accept the rest of the blocks in [chain1]. 355 if err := blockchain.Accept(chain1[0]); err != nil { 356 t.Fatal(err) 357 } 358 blockchain.DrainAcceptorQueue() 359 360 if blockchain.snaps != nil { 361 // Snap layer count should be 1 fewer 362 if want, got := len(chain1)+len(chain2), blockchain.snaps.NumBlockLayers(); got != want { 363 t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want) 364 } 365 } 366 367 for i := 0; i < len(chain2); i++ { 368 if err := blockchain.Reject(chain2[i]); err != nil { 369 t.Fatal(err) 370 } 371 372 if blockchain.snaps != nil { 373 // Snap layer count should decrease by 1 per Reject 374 if want, got := len(chain1)+len(chain2)-i-1, blockchain.snaps.NumBlockLayers(); got != want { 375 t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want) 376 } 377 } 378 } 379 380 if blockchain.snaps != nil { 381 if want, got := len(chain1), blockchain.snaps.NumBlockLayers(); got != want { 382 t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want) 383 } 384 } 385 386 for i := 1; i < len(chain1); i++ { 387 if err := blockchain.Accept(chain1[i]); err != nil { 388 t.Fatal(err) 389 } 390 blockchain.DrainAcceptorQueue() 391 392 if blockchain.snaps != nil { 393 // Snap layer count should decrease by 1 per Accept 394 if want, got := len(chain1)-i, blockchain.snaps.NumBlockLayers(); got != want { 395 t.Fatalf("incorrect snapshot layer count; got %d, want %d", got, want) 396 } 397 } 398 } 399 400 lastAcceptedBlock := blockchain.LastConsensusAcceptedBlock() 401 expectedLastAcceptedBlock := chain1[len(chain1)-1] 402 if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() { 403 t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64()) 404 } 405 if err := blockchain.ValidateCanonicalChain(); err != nil { 406 t.Fatal(err) 407 } 408 409 // check the state of the last accepted block 410 checkState := func(sdb *state.StateDB) error { 411 nonce1 := sdb.GetNonce(addr1) 412 if nonce1 != 129 { 413 return fmt.Errorf("expected addr1 nonce: 129, found nonce %d", nonce1) 414 } 415 balance1 := sdb.GetBalance(addr1) 416 transferredFunds := new(big.Int).Mul(big.NewInt(129), big.NewInt(10000)) 417 expectedBalance := new(big.Int).Sub(genesisBalance, transferredFunds) 418 if balance1.Cmp(expectedBalance) != 0 { 419 return fmt.Errorf("expected addr1 balance: %d, found balance: %d", expectedBalance, balance1) 420 } 421 nonce2 := sdb.GetNonce(addr2) 422 if nonce2 != 0 { 423 return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce2) 424 } 425 balance2 := sdb.GetBalance(addr2) 426 if balance2.Cmp(transferredFunds) != 0 { 427 return fmt.Errorf("expected addr2 balance: %d, found balance: %d", transferredFunds, balance2) 428 } 429 return nil 430 } 431 432 checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState) 433 } 434 435 func TestAcceptNonCanonicalBlock(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) { 436 var ( 437 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 438 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 439 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 440 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 441 // We use two separate databases since GenerateChain commits the state roots to its underlying 442 // database. 443 genDB = rawdb.NewMemoryDatabase() 444 chainDB = rawdb.NewMemoryDatabase() 445 ) 446 447 // Ensure that key1 has some funds in the genesis block. 448 genesisBalance := big.NewInt(1000000000) 449 gspec := &Genesis{ 450 Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, 451 Alloc: GenesisAlloc{addr1: {Balance: genesisBalance}}, 452 } 453 genesis := gspec.MustCommit(genDB) 454 _ = gspec.MustCommit(chainDB) 455 456 blockchain, err := create(chainDB, gspec.Config, common.Hash{}) 457 if err != nil { 458 t.Fatal(err) 459 } 460 defer blockchain.Stop() 461 462 numBlocks := 3 463 signer := types.HomesteadSigner{} 464 // Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing 465 // to the BlockChain's database while generating blocks. 466 chain1, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, 10, func(i int, gen *BlockGen) { 467 // Generate a transaction to create a unique block 468 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1) 469 gen.AddTx(tx) 470 }) 471 if err != nil { 472 t.Fatal(err) 473 } 474 chain2, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, 10, func(i int, gen *BlockGen) { 475 // Generate a transaction with a different amount to create a chain of blocks different from [chain1] 476 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(5000), params.TxGas, nil, nil), signer, key1) 477 gen.AddTx(tx) 478 }) 479 if err != nil { 480 t.Fatal(err) 481 } 482 483 // Insert three blocks into the chain and accept only the first. 484 if _, err := blockchain.InsertChain(chain1); err != nil { 485 t.Fatal(err) 486 } 487 if _, err := blockchain.InsertChain(chain2); err != nil { 488 t.Fatal(err) 489 } 490 491 currentBlock := blockchain.CurrentBlock() 492 expectedCurrentBlock := chain1[len(chain1)-1] 493 if currentBlock.Hash() != expectedCurrentBlock.Hash() { 494 t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64()) 495 } 496 497 if err := blockchain.ValidateCanonicalChain(); err != nil { 498 t.Fatal(err) 499 } 500 501 // Accept the first block in [chain2], reject all blocks in [chain1] to 502 // mimic the order that the consensus engine will call Accept/Reject in. 503 if err := blockchain.Accept(chain2[0]); err != nil { 504 t.Fatal(err) 505 } 506 blockchain.DrainAcceptorQueue() 507 508 for i := 0; i < len(chain1); i++ { 509 if err := blockchain.Reject(chain1[i]); err != nil { 510 t.Fatal(err) 511 } 512 } 513 514 lastAcceptedBlock := blockchain.LastConsensusAcceptedBlock() 515 expectedLastAcceptedBlock := chain2[0] 516 if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() { 517 t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64()) 518 } 519 if err := blockchain.ValidateCanonicalChain(); err != nil { 520 t.Fatal(err) 521 } 522 523 // check the state of the last accepted block 524 checkState := func(sdb *state.StateDB) error { 525 nonce1 := sdb.GetNonce(addr1) 526 if nonce1 != 1 { 527 return fmt.Errorf("expected addr1 nonce: 1, found nonce: %d", nonce1) 528 } 529 balance1 := sdb.GetBalance(addr1) 530 transferredFunds := big.NewInt(5000) 531 expectedBalance := new(big.Int).Sub(genesisBalance, transferredFunds) 532 if balance1.Cmp(expectedBalance) != 0 { 533 return fmt.Errorf("expected balance1: %d, found balance: %d", expectedBalance, balance1) 534 } 535 nonce2 := sdb.GetNonce(addr2) 536 if nonce2 != 0 { 537 return fmt.Errorf("expected addr2 nonce: 0, found nonce %d", nonce2) 538 } 539 balance2 := sdb.GetBalance(addr2) 540 if balance2.Cmp(transferredFunds) != 0 { 541 return fmt.Errorf("expected balance2: %d, found %d", transferredFunds, balance2) 542 } 543 return nil 544 } 545 546 checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState) 547 } 548 549 func TestSetPreferenceRewind(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) { 550 var ( 551 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 552 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 553 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 554 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 555 // We use two separate databases since GenerateChain commits the state roots to its underlying 556 // database. 557 genDB = rawdb.NewMemoryDatabase() 558 chainDB = rawdb.NewMemoryDatabase() 559 ) 560 561 // Ensure that key1 has some funds in the genesis block. 562 genesisBalance := big.NewInt(1000000000) 563 gspec := &Genesis{ 564 Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, 565 Alloc: GenesisAlloc{addr1: {Balance: genesisBalance}}, 566 } 567 genesis := gspec.MustCommit(genDB) 568 _ = gspec.MustCommit(chainDB) 569 570 blockchain, err := create(chainDB, gspec.Config, common.Hash{}) 571 if err != nil { 572 t.Fatal(err) 573 } 574 defer blockchain.Stop() 575 576 numBlocks := 3 577 signer := types.HomesteadSigner{} 578 // Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing 579 // to the BlockChain's database while generating blocks. 580 chain, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, 10, func(i int, gen *BlockGen) { 581 // Generate a transaction to create a unique block 582 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1) 583 gen.AddTx(tx) 584 }) 585 if err != nil { 586 t.Fatal(err) 587 } 588 589 // Insert three blocks into the chain and accept only the first. 590 if _, err := blockchain.InsertChain(chain); err != nil { 591 t.Fatal(err) 592 } 593 594 currentBlock := blockchain.CurrentBlock() 595 expectedCurrentBlock := chain[len(chain)-1] 596 if currentBlock.Hash() != expectedCurrentBlock.Hash() { 597 t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64()) 598 } 599 600 if err := blockchain.ValidateCanonicalChain(); err != nil { 601 t.Fatal(err) 602 } 603 604 // SetPreference to an ancestor of the currently preferred block. Test that this unlikely, but possible behavior 605 // is handled correctly. 606 if err := blockchain.SetPreference(chain[0]); err != nil { 607 t.Fatal(err) 608 } 609 610 currentBlock = blockchain.CurrentBlock() 611 expectedCurrentBlock = chain[0] 612 if currentBlock.Hash() != expectedCurrentBlock.Hash() { 613 t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64()) 614 } 615 616 lastAcceptedBlock := blockchain.LastConsensusAcceptedBlock() 617 expectedLastAcceptedBlock := blockchain.Genesis() 618 if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() { 619 t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64()) 620 } 621 if err := blockchain.ValidateCanonicalChain(); err != nil { 622 t.Fatal(err) 623 } 624 // check the state of the last accepted block 625 checkGenesisState := func(sdb *state.StateDB) error { 626 nonce1 := sdb.GetNonce(addr1) 627 if nonce1 != 0 { 628 return fmt.Errorf("expected addr1 nonce: 0, found nonce: %d", nonce1) 629 } 630 balance1 := sdb.GetBalance(addr1) 631 if balance1.Cmp(genesisBalance) != 0 { 632 return fmt.Errorf("expected addr1 balance: %d, found balance: %d", genesisBalance, balance1) 633 } 634 nonce2 := sdb.GetNonce(addr2) 635 if nonce2 != 0 { 636 return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce2) 637 } 638 balance2 := sdb.GetBalance(addr2) 639 if balance2.Cmp(big.NewInt(0)) != 0 { 640 return fmt.Errorf("expected addr2 balance: 0, found balance %d", balance2) 641 } 642 return nil 643 } 644 checkBlockChainState(t, blockchain, gspec, chainDB, create, checkGenesisState) 645 646 if err := blockchain.Accept(chain[0]); err != nil { 647 t.Fatal(err) 648 } 649 blockchain.DrainAcceptorQueue() 650 651 lastAcceptedBlock = blockchain.LastConsensusAcceptedBlock() 652 expectedLastAcceptedBlock = chain[0] 653 if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() { 654 t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64()) 655 } 656 if err := blockchain.ValidateCanonicalChain(); err != nil { 657 t.Fatal(err) 658 } 659 checkUpdatedState := func(sdb *state.StateDB) error { 660 nonce := sdb.GetNonce(addr1) 661 if nonce != 1 { 662 return fmt.Errorf("expected addr1 nonce: 1, found nonce: %d", nonce) 663 } 664 transferredFunds := big.NewInt(10000) 665 balance1 := sdb.GetBalance(addr1) 666 expectedBalance1 := new(big.Int).Sub(genesisBalance, transferredFunds) 667 if balance1.Cmp(expectedBalance1) != 0 { 668 return fmt.Errorf("expected addr1 balance: %d, found balance %d", expectedBalance1, balance1) 669 } 670 671 balance2 := sdb.GetBalance(addr2) 672 expectedBalance2 := transferredFunds 673 if balance2.Cmp(expectedBalance2) != 0 { 674 return fmt.Errorf("expected addr2 balance: %d, found balance: %d", expectedBalance2, balance2) 675 } 676 677 nonce = sdb.GetNonce(addr2) 678 if nonce != 0 { 679 return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce) 680 } 681 return nil 682 } 683 checkBlockChainState(t, blockchain, gspec, chainDB, create, checkUpdatedState) 684 } 685 686 func TestBuildOnVariousStages(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) { 687 var ( 688 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 689 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 690 key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee") 691 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 692 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 693 addr3 = crypto.PubkeyToAddress(key3.PublicKey) 694 // We use two separate databases since GenerateChain commits the state roots to its underlying 695 // database. 696 genDB = rawdb.NewMemoryDatabase() 697 chainDB = rawdb.NewMemoryDatabase() 698 ) 699 700 // Ensure that key1 has some funds in the genesis block. 701 genesisBalance := big.NewInt(1000000) 702 gspec := &Genesis{ 703 Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, 704 Alloc: GenesisAlloc{ 705 addr1: {Balance: genesisBalance}, 706 addr3: {Balance: genesisBalance}, 707 }, 708 } 709 genesis := gspec.MustCommit(genDB) 710 _ = gspec.MustCommit(chainDB) 711 712 blockchain, err := create(chainDB, gspec.Config, common.Hash{}) 713 if err != nil { 714 t.Fatal(err) 715 } 716 defer blockchain.Stop() 717 718 // This call generates a chain of 3 blocks. 719 signer := types.HomesteadSigner{} 720 // Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing 721 // to the BlockChain's database while generating blocks. 722 chain1, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 20, 10, func(i int, gen *BlockGen) { 723 // Send all funds back and forth between the two accounts 724 if i%2 == 0 { 725 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, genesisBalance, params.TxGas, nil, nil), signer, key1) 726 gen.AddTx(tx) 727 } else { 728 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr1, genesisBalance, params.TxGas, nil, nil), signer, key2) 729 gen.AddTx(tx) 730 } 731 }) 732 if err != nil { 733 t.Fatal(err) 734 } 735 // Build second chain forked off of the 10th block in [chain1] 736 chain2, _, err := GenerateChain(gspec.Config, chain1[9], blockchain.engine, genDB, 10, 10, func(i int, gen *BlockGen) { 737 // Send all funds back and forth between the two accounts 738 if i%2 == 0 { 739 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr2, genesisBalance, params.TxGas, nil, nil), signer, key3) 740 gen.AddTx(tx) 741 } else { 742 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr3, genesisBalance, params.TxGas, nil, nil), signer, key2) 743 gen.AddTx(tx) 744 } 745 }) 746 if err != nil { 747 t.Fatal(err) 748 } 749 // Build third chain forked off of the 5th block in [chain1]. 750 // The parent of this chain will be accepted before this fork 751 // is inserted. 752 chain3, _, err := GenerateChain(gspec.Config, chain1[4], blockchain.engine, genDB, 10, 10, func(i int, gen *BlockGen) { 753 // Send all funds back and forth between accounts 2 and 3. 754 if i%2 == 0 { 755 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr3, genesisBalance, params.TxGas, nil, nil), signer, key2) 756 gen.AddTx(tx) 757 } else { 758 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr2, genesisBalance, params.TxGas, nil, nil), signer, key3) 759 gen.AddTx(tx) 760 } 761 }) 762 if err != nil { 763 t.Fatal(err) 764 } 765 766 // Insert first 10 blocks from [chain1] 767 if _, err := blockchain.InsertChain(chain1); err != nil { 768 t.Fatal(err) 769 } 770 // Accept the first 5 blocks 771 for _, block := range chain1[0:5] { 772 if err := blockchain.Accept(block); err != nil { 773 t.Fatal(err) 774 } 775 } 776 blockchain.DrainAcceptorQueue() 777 778 // Insert the forked chain [chain2] which starts at the 10th 779 // block in [chain1] ie. a block that is still in processing. 780 if _, err := blockchain.InsertChain(chain2); err != nil { 781 t.Fatal(err) 782 } 783 // Insert another forked chain starting at the last accepted 784 // block from [chain1]. 785 if _, err := blockchain.InsertChain(chain3); err != nil { 786 t.Fatal(err) 787 } 788 // Accept the next block in [chain1] and then reject all 789 // of the blocks in [chain3], which would then be rejected. 790 if err := blockchain.Accept(chain1[5]); err != nil { 791 t.Fatal(err) 792 } 793 blockchain.DrainAcceptorQueue() 794 for _, block := range chain3 { 795 if err := blockchain.Reject(block); err != nil { 796 t.Fatal(err) 797 } 798 } 799 // Accept the rest of the blocks in [chain1] 800 for _, block := range chain1[6:10] { 801 if err := blockchain.Accept(block); err != nil { 802 t.Fatal(err) 803 } 804 } 805 blockchain.DrainAcceptorQueue() 806 807 // Accept the first block in [chain2] and reject the 808 // subsequent blocks in [chain1] which would then be rejected. 809 if err := blockchain.Accept(chain2[0]); err != nil { 810 t.Fatal(err) 811 } 812 blockchain.DrainAcceptorQueue() 813 814 for _, block := range chain1[10:] { 815 if err := blockchain.Reject(block); err != nil { 816 t.Fatal(err) 817 } 818 } 819 820 // check the state of the last accepted block 821 checkState := func(sdb *state.StateDB) error { 822 nonce := sdb.GetNonce(addr1) 823 if nonce != 5 { 824 return fmt.Errorf("expected nonce addr1: 5, found nonce: %d", nonce) 825 } 826 balance1 := sdb.GetBalance(addr1) 827 expectedBalance1 := genesisBalance 828 if balance1.Cmp(expectedBalance1) != 0 { 829 return fmt.Errorf("expected addr1 balance: %d, found balance: %d", expectedBalance1, balance1) 830 } 831 832 balance2 := sdb.GetBalance(addr2) 833 expectedBalance2 := genesisBalance 834 if balance2.Cmp(expectedBalance2) != 0 { 835 return fmt.Errorf("expected addr2 balance: %d, found balance: %d", expectedBalance2, balance2) 836 } 837 838 nonce = sdb.GetNonce(addr2) 839 if nonce != 5 { 840 return fmt.Errorf("expected addr2 nonce: 5, found nonce: %d", nonce) 841 } 842 843 balance3 := sdb.GetBalance(addr3) 844 expectedBalance3 := common.Big0 845 if balance3.Cmp(expectedBalance3) != 0 { 846 return fmt.Errorf("expected addr3 balance: %d, found balance: %d", expectedBalance3, balance3) 847 } 848 849 nonce = sdb.GetNonce(addr3) 850 if nonce != 1 { 851 return fmt.Errorf("expected addr3 nonce: 1, found nonce: %d", nonce) 852 } 853 return nil 854 } 855 856 checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState) 857 } 858 859 func TestEmptyBlocks(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) { 860 var ( 861 // We use two separate databases since GenerateChain commits the state roots to its underlying 862 // database. 863 genDB = rawdb.NewMemoryDatabase() 864 chainDB = rawdb.NewMemoryDatabase() 865 ) 866 867 // Ensure that key1 has some funds in the genesis block. 868 gspec := &Genesis{ 869 Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, 870 Alloc: GenesisAlloc{}, 871 } 872 genesis := gspec.MustCommit(genDB) 873 _ = gspec.MustCommit(chainDB) 874 875 blockchain, err := create(chainDB, gspec.Config, common.Hash{}) 876 if err != nil { 877 t.Fatal(err) 878 } 879 defer blockchain.Stop() 880 881 // Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing 882 // to the BlockChain's database while generating blocks. 883 chain, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, 10, func(i int, gen *BlockGen) {}) 884 if err != nil { 885 t.Fatal(err) 886 } 887 888 // Insert three blocks into the chain and accept only the first block. 889 if _, err := blockchain.InsertChain(chain); err != nil { 890 t.Fatal(err) 891 } 892 for _, block := range chain { 893 if err := blockchain.Accept(block); err != nil { 894 t.Fatal(err) 895 } 896 } 897 blockchain.DrainAcceptorQueue() 898 899 // Nothing to assert about the state 900 checkState := func(sdb *state.StateDB) error { 901 return nil 902 } 903 904 checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState) 905 } 906 907 func TestReorgReInsert(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) { 908 var ( 909 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 910 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 911 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 912 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 913 // We use two separate databases since GenerateChain commits the state roots to its underlying 914 // database. 915 genDB = rawdb.NewMemoryDatabase() 916 chainDB = rawdb.NewMemoryDatabase() 917 ) 918 919 // Ensure that key1 has some funds in the genesis block. 920 genesisBalance := big.NewInt(1000000000) 921 gspec := &Genesis{ 922 Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, 923 Alloc: GenesisAlloc{addr1: {Balance: genesisBalance}}, 924 } 925 genesis := gspec.MustCommit(genDB) 926 _ = gspec.MustCommit(chainDB) 927 928 blockchain, err := create(chainDB, gspec.Config, common.Hash{}) 929 if err != nil { 930 t.Fatal(err) 931 } 932 defer blockchain.Stop() 933 934 signer := types.HomesteadSigner{} 935 numBlocks := 3 936 chain, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, numBlocks, 10, func(i int, gen *BlockGen) { 937 // Generate a transaction to create a unique block 938 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1) 939 gen.AddTx(tx) 940 }) 941 if err != nil { 942 t.Fatal(err) 943 } 944 945 // Insert and accept first block 946 if err := blockchain.InsertBlock(chain[0]); err != nil { 947 t.Fatal(err) 948 } 949 if err := blockchain.Accept(chain[0]); err != nil { 950 t.Fatal(err) 951 } 952 953 // Insert block and then set preference back (rewind) to last accepted blck 954 if err := blockchain.InsertBlock(chain[1]); err != nil { 955 t.Fatal(err) 956 } 957 if err := blockchain.SetPreference(chain[0]); err != nil { 958 t.Fatal(err) 959 } 960 961 // Re-insert and accept block 962 if err := blockchain.InsertBlock(chain[1]); err != nil { 963 t.Fatal(err) 964 } 965 if err := blockchain.Accept(chain[1]); err != nil { 966 t.Fatal(err) 967 } 968 969 // Build on top of the re-inserted block and accept 970 if err := blockchain.InsertBlock(chain[2]); err != nil { 971 t.Fatal(err) 972 } 973 if err := blockchain.Accept(chain[2]); err != nil { 974 t.Fatal(err) 975 } 976 blockchain.DrainAcceptorQueue() 977 978 // Nothing to assert about the state 979 checkState := func(sdb *state.StateDB) error { 980 nonce1 := sdb.GetNonce(addr1) 981 if nonce1 != 3 { 982 return fmt.Errorf("expected addr1 nonce: 3, found nonce: %d", nonce1) 983 } 984 balance1 := sdb.GetBalance(addr1) 985 transferredFunds := big.NewInt(30000) 986 expectedBalance := new(big.Int).Sub(genesisBalance, transferredFunds) 987 if balance1.Cmp(expectedBalance) != 0 { 988 return fmt.Errorf("expected balance1: %d, found balance: %d", expectedBalance, balance1) 989 } 990 nonce2 := sdb.GetNonce(addr2) 991 if nonce2 != 0 { 992 return fmt.Errorf("expected addr2 nonce: 0, found nonce %d", nonce2) 993 } 994 balance2 := sdb.GetBalance(addr2) 995 if balance2.Cmp(transferredFunds) != 0 { 996 return fmt.Errorf("expected balance2: %d, found %d", transferredFunds, balance2) 997 } 998 return nil 999 } 1000 1001 checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState) 1002 } 1003 1004 // Insert two different chains that result in the identical state root. 1005 // Once we accept one of the chains, we insert and accept A3 on top of the shared 1006 // state root 1007 // G (genesis) 1008 // / \ 1009 // A1 B1 1010 // | | 1011 // A2 B2 (A2 and B2 represent two different paths to the identical state trie) 1012 // | 1013 // A3 1014 func TestAcceptBlockIdenticalStateRoot(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) { 1015 var ( 1016 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1017 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 1018 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1019 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 1020 // We use two separate databases since GenerateChain commits the state roots to its underlying 1021 // database. 1022 genDB = rawdb.NewMemoryDatabase() 1023 chainDB = rawdb.NewMemoryDatabase() 1024 ) 1025 1026 // Ensure that key1 has some funds in the genesis block. 1027 genesisBalance := big.NewInt(1000000000) 1028 gspec := &Genesis{ 1029 Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, 1030 Alloc: GenesisAlloc{addr1: {Balance: genesisBalance}}, 1031 } 1032 genesis := gspec.MustCommit(genDB) 1033 _ = gspec.MustCommit(chainDB) 1034 1035 blockchain, err := create(chainDB, gspec.Config, common.Hash{}) 1036 if err != nil { 1037 t.Fatal(err) 1038 } 1039 defer blockchain.Stop() 1040 1041 signer := types.HomesteadSigner{} 1042 // Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing 1043 // to the BlockChain's database while generating blocks. 1044 chain1, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, 10, func(i int, gen *BlockGen) { 1045 if i < 2 { 1046 // Send half the funds from addr1 to addr2 in one transaction per each of the two blocks in [chain1] 1047 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(500000000), params.TxGas, nil, nil), signer, key1) 1048 gen.AddTx(tx) 1049 } 1050 // Allow the third block to be empty. 1051 }) 1052 if err != nil { 1053 t.Fatal(err) 1054 } 1055 chain2, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 2, 10, func(i int, gen *BlockGen) { 1056 // Send 1/4 of the funds from addr1 to addr2 in tx1 and 3/4 of the funds in tx2. This will produce the identical state 1057 // root in the second block of [chain2] as is present in the second block of [chain1]. 1058 if i == 0 { 1059 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(250000000), params.TxGas, nil, nil), signer, key1) 1060 gen.AddTx(tx) 1061 } else { 1062 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(750000000), params.TxGas, nil, nil), signer, key1) 1063 gen.AddTx(tx) 1064 } 1065 }) 1066 if err != nil { 1067 t.Fatal(err) 1068 } 1069 1070 // Assert that the block root of the second block in both chains is identical 1071 if chain1[1].Root() != chain2[1].Root() { 1072 t.Fatalf("Expected the latter block in both chain1 and chain2 to have identical state root, but found %s and %s", chain1[1].Root(), chain2[1].Root()) 1073 } 1074 1075 // Insert first two blocks of [chain1] and both blocks in [chain2] 1076 // This leaves us one additional block to insert on top of [chain1] 1077 // after testing that the state roots are handled correctly. 1078 if _, err := blockchain.InsertChain(chain1[:2]); err != nil { 1079 t.Fatal(err) 1080 } 1081 if _, err := blockchain.InsertChain(chain2); err != nil { 1082 t.Fatal(err) 1083 } 1084 1085 currentBlock := blockchain.CurrentBlock() 1086 expectedCurrentBlock := chain1[1] 1087 if currentBlock.Hash() != expectedCurrentBlock.Hash() { 1088 t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64()) 1089 } 1090 1091 // Accept the first block in [chain1] and reject all of [chain2] 1092 if err := blockchain.Accept(chain1[0]); err != nil { 1093 t.Fatal(err) 1094 } 1095 blockchain.DrainAcceptorQueue() 1096 1097 for _, block := range chain2 { 1098 if err := blockchain.Reject(block); err != nil { 1099 t.Fatal(err) 1100 } 1101 } 1102 1103 // Accept the last two blocks in [chain1]. This is a regression test to ensure 1104 // that we do not discard a snapshot difflayer that is still in use by a 1105 // processing block, when a different block with the same root is rejected. 1106 if err := blockchain.Accept(chain1[1]); err != nil { 1107 t.Fatal(err) 1108 } 1109 blockchain.DrainAcceptorQueue() 1110 1111 lastAcceptedBlock := blockchain.LastConsensusAcceptedBlock() 1112 expectedLastAcceptedBlock := chain1[1] 1113 if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() { 1114 t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64()) 1115 } 1116 1117 if err := blockchain.InsertBlock(chain1[2]); err != nil { 1118 t.Fatal(err) 1119 } 1120 if err := blockchain.Accept(chain1[2]); err != nil { 1121 t.Fatal(err) 1122 } 1123 blockchain.DrainAcceptorQueue() 1124 1125 // check the state of the last accepted block 1126 checkState := func(sdb *state.StateDB) error { 1127 nonce1 := sdb.GetNonce(addr1) 1128 if nonce1 != 2 { 1129 return fmt.Errorf("expected addr1 nonce: 2, found nonce: %d", nonce1) 1130 } 1131 balance1 := sdb.GetBalance(addr1) 1132 expectedBalance := common.Big0 1133 if balance1.Cmp(expectedBalance) != 0 { 1134 return fmt.Errorf("expected balance1: %d, found balance: %d", expectedBalance, balance1) 1135 } 1136 nonce2 := sdb.GetNonce(addr2) 1137 if nonce2 != 0 { 1138 return fmt.Errorf("expected addr2 nonce: 0, found nonce %d", nonce2) 1139 } 1140 balance2 := sdb.GetBalance(addr2) 1141 if balance2.Cmp(genesisBalance) != 0 { 1142 return fmt.Errorf("expected balance2: %d, found %d", genesisBalance, balance2) 1143 } 1144 return nil 1145 } 1146 1147 checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState) 1148 } 1149 1150 // Insert two different chains that result in the identical state root. 1151 // Once we insert both of the chains, we restart, insert both the chains again, 1152 // and then we accept one of the chains and accept A3 on top of the shared state 1153 // root 1154 // G (genesis) 1155 // / \ 1156 // A1 B1 1157 // | | 1158 // A2 B2 (A2 and B2 represent two different paths to the identical state trie) 1159 // | 1160 // A3 1161 func TestReprocessAcceptBlockIdenticalStateRoot(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) { 1162 var ( 1163 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1164 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 1165 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1166 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 1167 // We use two separate databases since GenerateChain commits the state roots to its underlying 1168 // database. 1169 genDB = rawdb.NewMemoryDatabase() 1170 chainDB = rawdb.NewMemoryDatabase() 1171 ) 1172 1173 // Ensure that key1 has some funds in the genesis block. 1174 genesisBalance := big.NewInt(1000000000) 1175 gspec := &Genesis{ 1176 Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, 1177 Alloc: GenesisAlloc{addr1: {Balance: genesisBalance}}, 1178 } 1179 genesis := gspec.MustCommit(genDB) 1180 _ = gspec.MustCommit(chainDB) 1181 1182 blockchain, err := create(chainDB, gspec.Config, common.Hash{}) 1183 if err != nil { 1184 t.Fatal(err) 1185 } 1186 1187 signer := types.HomesteadSigner{} 1188 // Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing 1189 // to the BlockChain's database while generating blocks. 1190 chain1, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, 10, func(i int, gen *BlockGen) { 1191 if i < 2 { 1192 // Send half the funds from addr1 to addr2 in one transaction per each of the two blocks in [chain1] 1193 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(500000000), params.TxGas, nil, nil), signer, key1) 1194 gen.AddTx(tx) 1195 } 1196 // Allow the third block to be empty. 1197 }) 1198 if err != nil { 1199 t.Fatal(err) 1200 } 1201 chain2, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 2, 10, func(i int, gen *BlockGen) { 1202 // Send 1/4 of the funds from addr1 to addr2 in tx1 and 3/4 of the funds in tx2. This will produce the identical state 1203 // root in the second block of [chain2] as is present in the second block of [chain1]. 1204 if i == 0 { 1205 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(250000000), params.TxGas, nil, nil), signer, key1) 1206 gen.AddTx(tx) 1207 } else { 1208 tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(750000000), params.TxGas, nil, nil), signer, key1) 1209 gen.AddTx(tx) 1210 } 1211 }) 1212 if err != nil { 1213 t.Fatal(err) 1214 } 1215 1216 // Assert that the block root of the second block in both chains is identical 1217 if chain1[1].Root() != chain2[1].Root() { 1218 t.Fatalf("Expected the latter block in both chain1 and chain2 to have identical state root, but found %s and %s", chain1[1].Root(), chain2[1].Root()) 1219 } 1220 1221 // Insert first two blocks of [chain1] and both blocks in [chain2] 1222 // This leaves us one additional block to insert on top of [chain1] 1223 // after testing that the state roots are handled correctly. 1224 if _, err := blockchain.InsertChain(chain1[:2]); err != nil { 1225 t.Fatal(err) 1226 } 1227 if _, err := blockchain.InsertChain(chain2); err != nil { 1228 t.Fatal(err) 1229 } 1230 1231 currentBlock := blockchain.CurrentBlock() 1232 expectedCurrentBlock := chain1[1] 1233 if currentBlock.Hash() != expectedCurrentBlock.Hash() { 1234 t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64()) 1235 } 1236 1237 blockchain.Stop() 1238 1239 blockchain, err = create(chainDB, gspec.Config, common.Hash{}) 1240 if err != nil { 1241 t.Fatal(err) 1242 } 1243 defer blockchain.Stop() 1244 1245 // Insert first two blocks of [chain1] and both blocks in [chain2] 1246 // This leaves us one additional block to insert on top of [chain1] 1247 // after testing that the state roots are handled correctly. 1248 if _, err := blockchain.InsertChain(chain1[:2]); err != nil { 1249 t.Fatal(err) 1250 } 1251 if _, err := blockchain.InsertChain(chain2); err != nil { 1252 t.Fatal(err) 1253 } 1254 1255 currentBlock = blockchain.CurrentBlock() 1256 expectedCurrentBlock = chain1[1] 1257 if currentBlock.Hash() != expectedCurrentBlock.Hash() { 1258 t.Fatalf("Expected current block to be %s:%d, but found %s%d", expectedCurrentBlock.Hash().Hex(), expectedCurrentBlock.NumberU64(), currentBlock.Hash().Hex(), currentBlock.NumberU64()) 1259 } 1260 1261 // Accept the first block in [chain1] and reject all of [chain2] 1262 if err := blockchain.Accept(chain1[0]); err != nil { 1263 t.Fatal(err) 1264 } 1265 blockchain.DrainAcceptorQueue() 1266 1267 for _, block := range chain2 { 1268 if err := blockchain.Reject(block); err != nil { 1269 t.Fatal(err) 1270 } 1271 } 1272 1273 // Accept the last two blocks in [chain1]. This is a regression test to ensure 1274 // that we do not discard a snapshot difflayer that is still in use by a 1275 // processing block, when a different block with the same root is rejected. 1276 if err := blockchain.Accept(chain1[1]); err != nil { 1277 t.Fatal(err) 1278 } 1279 blockchain.DrainAcceptorQueue() 1280 1281 lastAcceptedBlock := blockchain.LastConsensusAcceptedBlock() 1282 expectedLastAcceptedBlock := chain1[1] 1283 if lastAcceptedBlock.Hash() != expectedLastAcceptedBlock.Hash() { 1284 t.Fatalf("Expected last accepted block to be %s:%d, but found %s%d", expectedLastAcceptedBlock.Hash().Hex(), expectedLastAcceptedBlock.NumberU64(), lastAcceptedBlock.Hash().Hex(), lastAcceptedBlock.NumberU64()) 1285 } 1286 1287 if err := blockchain.InsertBlock(chain1[2]); err != nil { 1288 t.Fatal(err) 1289 } 1290 if err := blockchain.Accept(chain1[2]); err != nil { 1291 t.Fatal(err) 1292 } 1293 blockchain.DrainAcceptorQueue() 1294 1295 // check the state of the last accepted block 1296 checkState := func(sdb *state.StateDB) error { 1297 nonce1 := sdb.GetNonce(addr1) 1298 if nonce1 != 2 { 1299 return fmt.Errorf("expected addr1 nonce: 2, found nonce: %d", nonce1) 1300 } 1301 balance1 := sdb.GetBalance(addr1) 1302 expectedBalance := common.Big0 1303 if balance1.Cmp(expectedBalance) != 0 { 1304 return fmt.Errorf("expected balance1: %d, found balance: %d", expectedBalance, balance1) 1305 } 1306 nonce2 := sdb.GetNonce(addr2) 1307 if nonce2 != 0 { 1308 return fmt.Errorf("expected addr2 nonce: 0, found nonce %d", nonce2) 1309 } 1310 balance2 := sdb.GetBalance(addr2) 1311 if balance2.Cmp(genesisBalance) != 0 { 1312 return fmt.Errorf("expected balance2: %d, found %d", genesisBalance, balance2) 1313 } 1314 return nil 1315 } 1316 1317 checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState) 1318 } 1319 1320 func TestGenerateChainInvalidBlockFee(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) { 1321 var ( 1322 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1323 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 1324 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1325 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 1326 // We use two separate databases since GenerateChain commits the state roots to its underlying 1327 // database. 1328 genDB = rawdb.NewMemoryDatabase() 1329 chainDB = rawdb.NewMemoryDatabase() 1330 ) 1331 1332 // Ensure that key1 has some funds in the genesis block. 1333 genesisBalance := new(big.Int).Mul(big.NewInt(1000000), big.NewInt(params.Ether)) 1334 gspec := &Genesis{ 1335 Config: params.TestChainConfig, 1336 Alloc: GenesisAlloc{addr1: {Balance: genesisBalance}}, 1337 } 1338 genesis := gspec.MustCommit(genDB) 1339 _ = gspec.MustCommit(chainDB) 1340 1341 blockchain, err := create(chainDB, gspec.Config, common.Hash{}) 1342 if err != nil { 1343 t.Fatal(err) 1344 } 1345 defer blockchain.Stop() 1346 1347 // This call generates a chain of 3 blocks. 1348 signer := types.LatestSigner(params.TestChainConfig) 1349 // Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing 1350 // to the BlockChain's database while generating blocks. 1351 _, _, err = GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, 0, func(i int, gen *BlockGen) { 1352 tx := types.NewTx(&types.DynamicFeeTx{ 1353 ChainID: params.TestChainConfig.ChainID, 1354 Nonce: gen.TxNonce(addr1), 1355 To: &addr2, 1356 Gas: params.TxGas, 1357 GasFeeCap: gen.BaseFee(), 1358 GasTipCap: big.NewInt(0), 1359 Data: []byte{}, 1360 }) 1361 1362 signedTx, err := types.SignTx(tx, signer, key1) 1363 if err != nil { 1364 t.Fatal(err) 1365 } 1366 gen.AddTx(signedTx) 1367 }) 1368 if err == nil { 1369 t.Fatal("should not have been able to build a block because of insufficient block fee") 1370 } 1371 if !strings.Contains(err.Error(), "insufficient gas (0) to cover the block cost (400000)") { 1372 t.Fatalf("should have gotten insufficient block fee error but got %v instead", err) 1373 } 1374 } 1375 1376 func TestInsertChainInvalidBlockFee(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) { 1377 var ( 1378 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1379 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 1380 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1381 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 1382 // We use two separate databases since GenerateChain commits the state roots to its underlying 1383 // database. 1384 genDB = rawdb.NewMemoryDatabase() 1385 chainDB = rawdb.NewMemoryDatabase() 1386 ) 1387 1388 // Ensure that key1 has some funds in the genesis block. 1389 genesisBalance := new(big.Int).Mul(big.NewInt(1000000), big.NewInt(params.Ether)) 1390 gspec := &Genesis{ 1391 Config: params.TestChainConfig, 1392 Alloc: GenesisAlloc{addr1: {Balance: genesisBalance}}, 1393 } 1394 genesis := gspec.MustCommit(genDB) 1395 _ = gspec.MustCommit(chainDB) 1396 1397 blockchain, err := create(chainDB, gspec.Config, common.Hash{}) 1398 if err != nil { 1399 t.Fatal(err) 1400 } 1401 defer blockchain.Stop() 1402 1403 // This call generates a chain of 3 blocks. 1404 signer := types.LatestSigner(params.TestChainConfig) 1405 // Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing 1406 // to the BlockChain's database while generating blocks. 1407 chain, _, err := GenerateChain(params.TestChainConfig, genesis, dummy.NewETHFaker(), genDB, 3, 0, func(i int, gen *BlockGen) { 1408 tx := types.NewTx(&types.DynamicFeeTx{ 1409 ChainID: params.TestChainConfig.ChainID, 1410 Nonce: gen.TxNonce(addr1), 1411 To: &addr2, 1412 Gas: params.TxGas, 1413 GasFeeCap: gen.BaseFee(), 1414 GasTipCap: big.NewInt(0), 1415 Data: []byte{}, 1416 }) 1417 1418 signedTx, err := types.SignTx(tx, signer, key1) 1419 if err != nil { 1420 t.Fatal(err) 1421 } 1422 gen.AddTx(signedTx) 1423 }) 1424 if err != nil { 1425 t.Fatal(err) 1426 } 1427 _, err = blockchain.InsertChain(chain) 1428 if err == nil { 1429 t.Fatal("should not have been able to build a block because of insufficient block fee") 1430 } 1431 if !strings.Contains(err.Error(), "insufficient gas (0) to cover the block cost (400000)") { 1432 t.Fatalf("should have gotten insufficient block fee error but got %v instead", err) 1433 } 1434 } 1435 1436 func TestInsertChainValidBlockFee(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) { 1437 var ( 1438 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1439 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 1440 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1441 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 1442 // We use two separate databases since GenerateChain commits the state roots to its underlying 1443 // database. 1444 genDB = rawdb.NewMemoryDatabase() 1445 chainDB = rawdb.NewMemoryDatabase() 1446 ) 1447 1448 // Ensure that key1 has some funds in the genesis block. 1449 genesisBalance := new(big.Int).Mul(big.NewInt(1000000), big.NewInt(params.Ether)) 1450 gspec := &Genesis{ 1451 Config: params.TestChainConfig, 1452 Alloc: GenesisAlloc{addr1: {Balance: genesisBalance}}, 1453 } 1454 genesis := gspec.MustCommit(genDB) 1455 _ = gspec.MustCommit(chainDB) 1456 1457 blockchain, err := create(chainDB, gspec.Config, common.Hash{}) 1458 if err != nil { 1459 t.Fatal(err) 1460 } 1461 defer blockchain.Stop() 1462 1463 // This call generates a chain of 3 blocks. 1464 signer := types.LatestSigner(params.TestChainConfig) 1465 // Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing 1466 // to the BlockChain's database while generating blocks. 1467 tip := big.NewInt(50000 * params.GWei) 1468 transfer := big.NewInt(10000) 1469 chain, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, 0, func(i int, gen *BlockGen) { 1470 feeCap := new(big.Int).Add(gen.BaseFee(), tip) 1471 tx := types.NewTx(&types.DynamicFeeTx{ 1472 ChainID: params.TestChainConfig.ChainID, 1473 Nonce: gen.TxNonce(addr1), 1474 To: &addr2, 1475 Gas: params.TxGas, 1476 Value: transfer, 1477 GasFeeCap: feeCap, 1478 GasTipCap: tip, 1479 Data: []byte{}, 1480 }) 1481 1482 signedTx, err := types.SignTx(tx, signer, key1) 1483 if err != nil { 1484 t.Fatal(err) 1485 } 1486 gen.AddTx(signedTx) 1487 }) 1488 if err != nil { 1489 t.Fatal(err) 1490 } 1491 1492 // Insert three blocks into the chain and accept only the first block. 1493 if _, err := blockchain.InsertChain(chain); err != nil { 1494 t.Fatal(err) 1495 } 1496 if err := blockchain.Accept(chain[0]); err != nil { 1497 t.Fatal(err) 1498 } 1499 blockchain.DrainAcceptorQueue() 1500 1501 // check the state of the last accepted block 1502 checkState := func(sdb *state.StateDB) error { 1503 nonce := sdb.GetNonce(addr1) 1504 if nonce != 1 { 1505 return fmt.Errorf("expected nonce addr1: 1, found nonce: %d", nonce) 1506 } 1507 balance1 := sdb.GetBalance(addr1) 1508 expectedBalance1 := new(big.Int).Sub(genesisBalance, transfer) 1509 baseFee := params.DefaultFeeConfig.MinBaseFee 1510 feeSpend := new(big.Int).Mul(new(big.Int).Add(baseFee, tip), new(big.Int).SetUint64(params.TxGas)) 1511 expectedBalance1.Sub(expectedBalance1, feeSpend) 1512 if balance1.Cmp(expectedBalance1) != 0 { 1513 return fmt.Errorf("expected addr1 balance: %d, found balance: %d", expectedBalance1, balance1) 1514 } 1515 1516 balance2 := sdb.GetBalance(addr2) 1517 expectedBalance2 := transfer 1518 if balance2.Cmp(expectedBalance2) != 0 { 1519 return fmt.Errorf("expected addr2 balance: %d, found balance: %d", expectedBalance2, balance2) 1520 } 1521 1522 nonce = sdb.GetNonce(addr2) 1523 if nonce != 0 { 1524 return fmt.Errorf("expected addr2 nonce: 0, found nonce: %d", nonce) 1525 } 1526 return nil 1527 } 1528 1529 checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState) 1530 } 1531 1532 // TestStatefulPrecompiles provides a testing framework to ensure that processing transactions interacting with the stateful precompiles work as expected. 1533 func TestStatefulPrecompiles(t *testing.T, create func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error)) { 1534 var ( 1535 key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 1536 key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") 1537 addr1 = crypto.PubkeyToAddress(key1.PublicKey) 1538 addr2 = crypto.PubkeyToAddress(key2.PublicKey) 1539 // We use two separate databases since GenerateChain commits the state roots to its underlying 1540 // database. 1541 genDB = rawdb.NewMemoryDatabase() 1542 chainDB = rawdb.NewMemoryDatabase() 1543 ) 1544 1545 // Ensure that key1 has sufficient funds in the genesis block for all of the tests. 1546 genesisBalance := new(big.Int).Mul(big.NewInt(1000000), big.NewInt(params.Ether)) 1547 config := *params.TestChainConfig 1548 // Set all of the required config parameters 1549 config.ContractDeployerAllowListConfig = precompile.NewContractDeployerAllowListConfig(big.NewInt(0), []common.Address{addr1}, nil) 1550 config.FeeManagerConfig = precompile.NewFeeManagerConfig(big.NewInt(0), []common.Address{addr1}, nil, nil) 1551 gspec := &Genesis{ 1552 Config: &config, 1553 Alloc: GenesisAlloc{addr1: {Balance: genesisBalance}}, 1554 } 1555 genesis := gspec.MustCommit(genDB) 1556 _ = gspec.MustCommit(chainDB) 1557 1558 blockchain, err := create(chainDB, gspec.Config, common.Hash{}) 1559 if err != nil { 1560 t.Fatal(err) 1561 } 1562 defer blockchain.Stop() 1563 1564 signer := types.LatestSigner(params.TestChainConfig) 1565 tip := big.NewInt(50000 * params.GWei) 1566 1567 // Simple framework to add a test that the stateful precompile works as expected 1568 type test struct { 1569 addTx func(gen *BlockGen) 1570 verifyGenesis func(sdb *state.StateDB) 1571 verifyState func(sdb *state.StateDB) error 1572 } 1573 testFeeConfig := commontype.FeeConfig{ 1574 GasLimit: big.NewInt(11_000_000), 1575 TargetBlockRate: 5, // in seconds 1576 1577 MinBaseFee: big.NewInt(28_000_000_000), 1578 TargetGas: big.NewInt(18_000_000), 1579 BaseFeeChangeDenominator: big.NewInt(3396), 1580 1581 MinBlockGasCost: big.NewInt(0), 1582 MaxBlockGasCost: big.NewInt(4_000_000), 1583 BlockGasCostStep: big.NewInt(500_000), 1584 } 1585 assert := assert.New(t) 1586 tests := map[string]test{ 1587 "allow list": { 1588 addTx: func(gen *BlockGen) { 1589 feeCap := new(big.Int).Add(gen.BaseFee(), tip) 1590 input, err := precompile.PackModifyAllowList(addr2, precompile.AllowListAdmin) 1591 if err != nil { 1592 t.Fatal(err) 1593 } 1594 tx := types.NewTx(&types.DynamicFeeTx{ 1595 ChainID: params.TestChainConfig.ChainID, 1596 Nonce: gen.TxNonce(addr1), 1597 To: &precompile.ContractDeployerAllowListAddress, 1598 Gas: 3_000_000, 1599 Value: common.Big0, 1600 GasFeeCap: feeCap, 1601 GasTipCap: tip, 1602 Data: input, 1603 }) 1604 1605 signedTx, err := types.SignTx(tx, signer, key1) 1606 if err != nil { 1607 t.Fatal(err) 1608 } 1609 gen.AddTx(signedTx) 1610 }, 1611 verifyState: func(sdb *state.StateDB) error { 1612 res := precompile.GetContractDeployerAllowListStatus(sdb, addr1) 1613 if precompile.AllowListAdmin != res { 1614 return fmt.Errorf("unexpected allow list status for addr1 %s, expected %s", res, precompile.AllowListAdmin) 1615 } 1616 res = precompile.GetContractDeployerAllowListStatus(sdb, addr2) 1617 if precompile.AllowListAdmin != res { 1618 return fmt.Errorf("unexpected allow list status for addr2 %s, expected %s", res, precompile.AllowListAdmin) 1619 } 1620 return nil 1621 }, 1622 verifyGenesis: func(sdb *state.StateDB) { 1623 res := precompile.GetContractDeployerAllowListStatus(sdb, addr1) 1624 if precompile.AllowListAdmin != res { 1625 t.Fatalf("unexpected allow list status for addr1 %s, expected %s", res, precompile.AllowListAdmin) 1626 } 1627 res = precompile.GetContractDeployerAllowListStatus(sdb, addr2) 1628 if precompile.AllowListNoRole != res { 1629 t.Fatalf("unexpected allow list status for addr2 %s, expected %s", res, precompile.AllowListNoRole) 1630 } 1631 }, 1632 }, 1633 "fee manager set config": { 1634 addTx: func(gen *BlockGen) { 1635 feeCap := new(big.Int).Add(gen.BaseFee(), tip) 1636 input, err := precompile.PackSetFeeConfig(testFeeConfig) 1637 if err != nil { 1638 t.Fatal(err) 1639 } 1640 tx := types.NewTx(&types.DynamicFeeTx{ 1641 ChainID: params.TestChainConfig.ChainID, 1642 Nonce: gen.TxNonce(addr1), 1643 To: &precompile.FeeConfigManagerAddress, 1644 Gas: 3_000_000, 1645 Value: common.Big0, 1646 GasFeeCap: feeCap, 1647 GasTipCap: tip, 1648 Data: input, 1649 }) 1650 1651 signedTx, err := types.SignTx(tx, signer, key1) 1652 if err != nil { 1653 t.Fatal(err) 1654 } 1655 gen.AddTx(signedTx) 1656 }, 1657 verifyState: func(sdb *state.StateDB) error { 1658 res := precompile.GetFeeConfigManagerStatus(sdb, addr1) 1659 assert.Equal(precompile.AllowListAdmin, res) 1660 1661 storedConfig := precompile.GetStoredFeeConfig(sdb) 1662 assert.EqualValues(testFeeConfig, storedConfig) 1663 1664 feeConfig, _, err := blockchain.GetFeeConfigAt(blockchain.CurrentHeader()) 1665 assert.NoError(err) 1666 assert.EqualValues(testFeeConfig, feeConfig) 1667 return nil 1668 }, 1669 verifyGenesis: func(sdb *state.StateDB) { 1670 res := precompile.GetFeeConfigManagerStatus(sdb, addr1) 1671 assert.Equal(precompile.AllowListAdmin, res) 1672 1673 feeConfig, _, err := blockchain.GetFeeConfigAt(blockchain.Genesis().Header()) 1674 assert.NoError(err) 1675 assert.EqualValues(config.FeeConfig, feeConfig) 1676 }, 1677 }, 1678 } 1679 1680 // Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing 1681 // to the BlockChain's database while generating blocks. 1682 chain, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 1, 0, func(i int, gen *BlockGen) { 1683 for _, test := range tests { 1684 test.addTx(gen) 1685 } 1686 }) 1687 if err != nil { 1688 t.Fatal(err) 1689 } 1690 1691 // Insert three blocks into the chain and accept only the first block. 1692 if _, err := blockchain.InsertChain(chain); err != nil { 1693 t.Fatal(err) 1694 } 1695 if err := blockchain.Accept(chain[0]); err != nil { 1696 t.Fatal(err) 1697 } 1698 blockchain.DrainAcceptorQueue() 1699 1700 genesisState, err := blockchain.StateAt(blockchain.Genesis().Root()) 1701 if err != nil { 1702 t.Fatal(err) 1703 } 1704 for _, test := range tests { 1705 if test.verifyGenesis == nil { 1706 continue 1707 } 1708 test.verifyGenesis(genesisState) 1709 } 1710 1711 // Run all of the necessary state verification 1712 checkState := func(sdb *state.StateDB) error { 1713 for _, test := range tests { 1714 if err := test.verifyState(sdb); err != nil { 1715 return err 1716 } 1717 } 1718 return nil 1719 } 1720 1721 // This tests that the precompiles work as expected when they are enabled 1722 checkBlockChainState(t, blockchain, gspec, chainDB, create, checkState) 1723 }