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