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