diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index a4c96ff6d3..e885ca18ad 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -103,7 +103,7 @@ func runCmd(ctx *cli.Context) error { gen := readGenesis(ctx.String(GenesisFlag.Name)) genesisConfig = gen db := rawdb.NewMemoryDatabase() - genesis := gen.ToBlock(db) + genesis := gen.MustCommit(db) statedb, _ = state.New(genesis.Root(), state.NewDatabase(db)) chainConfig = gen.Config } else { diff --git a/core/bench_test.go b/core/bench_test.go index f0c206871c..484937b38e 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -161,9 +161,9 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { // Generate a chain of b.N blocks using the supplied block // generator function. - gspec := Genesis{ - Config: params.TestChainConfig, + gspec := &Genesis{ Alloc: types.GenesisAlloc{benchRootAddr: {Balance: benchRootFunds}}, + Config: params.TestChainConfig, } genesis := gspec.MustCommit(db) chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, b.N, gen) diff --git a/core/block_validator_test.go b/core/block_validator_test.go index 79d6e5505f..34e493cca3 100644 --- a/core/block_validator_test.go +++ b/core/block_validator_test.go @@ -34,14 +34,14 @@ func TestHeaderVerification(t *testing.T) { testdb = rawdb.NewMemoryDatabase() gspec = &Genesis{Config: params.TestChainConfig} genesis = gspec.MustCommit(testdb) - blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 8, nil) + blocks, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), testdb, 8, nil) ) headers := make([]*types.Header, len(blocks)) for i, block := range blocks { headers[i] = block.Header() } // Run the header checker for blocks one-by-one, checking for both valid and invalid nonces - chain, err := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}) + chain, err := NewBlockChain(testdb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}) defer chain.Stop() if err != nil { t.Fatal(err) diff --git a/core/blockchain_test.go b/core/blockchain_test.go index e24becd0b3..85a8b06d68 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -592,9 +592,9 @@ func TestFastVsFullChains(t *testing.T) { address = crypto.PubkeyToAddress(key.PublicKey) funds = big.NewInt(1000000000000000) gspec = &Genesis{ - Config: params.TestChainConfig, Alloc: types.GenesisAlloc{address: {Balance: funds}}, BaseFee: big.NewInt(params.InitialBaseFee), + Config: params.TestChainConfig, } genesis = gspec.MustCommit(gendb) signer = types.LatestSigner(gspec.Config) @@ -681,9 +681,9 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { address = crypto.PubkeyToAddress(key.PublicKey) funds = big.NewInt(1000000000000000) gspec = &Genesis{ - Config: params.TestChainConfig, Alloc: types.GenesisAlloc{address: {Balance: funds}}, BaseFee: big.NewInt(params.InitialBaseFee), + Config: params.TestChainConfig, } genesis = gspec.MustCommit(gendb) ) @@ -767,13 +767,13 @@ func TestChainTxReorgs(t *testing.T) { addr3 = crypto.PubkeyToAddress(key3.PublicKey) db = rawdb.NewMemoryDatabase() gspec = &Genesis{ - Config: params.TestChainConfig, GasLimit: 3141592, Alloc: types.GenesisAlloc{ addr1: {Balance: big.NewInt(1000000000000000)}, addr2: {Balance: big.NewInt(1000000000000000)}, addr3: {Balance: big.NewInt(1000000000000000)}, }, + Config: params.TestChainConfig, } genesis = gspec.MustCommit(db) signer = types.LatestSigner(gspec.Config) @@ -878,8 +878,11 @@ func TestLogReorgs(t *testing.T) { addr1 = crypto.PubkeyToAddress(key1.PublicKey) db = rawdb.NewMemoryDatabase() // this code generates a log - code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") - gspec = &Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}} + code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") + gspec = &Genesis{ + Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}, + Config: params.TestChainConfig, + } genesis = gspec.MustCommit(db) signer = types.LatestSigner(gspec.Config) ) @@ -889,7 +892,7 @@ func TestLogReorgs(t *testing.T) { rmLogsCh := make(chan RemovedLogsEvent) blockchain.SubscribeRemovedLogsEvent(rmLogsCh) - chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { + chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { if i == 1 { tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, gen.header.BaseFee, code), signer, key1) if err != nil { @@ -902,7 +905,7 @@ func TestLogReorgs(t *testing.T) { t.Fatalf("failed to insert chain: %v", err) } - chain, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) + chain, _ = GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) if _, err := blockchain.InsertChain(chain); err != nil { t.Fatalf("failed to insert forked chain: %v", err) } @@ -1228,11 +1231,11 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { db := rawdb.NewMemoryDatabase() gspec := &Genesis{ - Config: params.TestChainConfig, BaseFee: big.NewInt(params.InitialBaseFee), + Config: params.TestChainConfig, } genesis := gspec.MustCommit(db) - blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) + blocks, _ := GenerateChain(gspec.Config, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) // Generate a bunch of fork blocks, each side forking from the canonical chain forks := make([]*types.Block, len(blocks)) @@ -1241,7 +1244,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { if i > 0 { parent = blocks[i-1] } - fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) + fork, _ := GenerateChain(gspec.Config, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) forks[i] = fork[0] } // Import the canonical and fork chain side by side, verifying the current block @@ -1249,7 +1252,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { diskdb := rawdb.NewMemoryDatabase() gspec.MustCommit(diskdb) - chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) + chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -1276,11 +1279,12 @@ func TestTrieForkGC(t *testing.T) { engine := ethash.NewFaker() db := rawdb.NewMemoryDatabase() - genesis := (&Genesis{ - Config: params.TestChainConfig, + gspec := &Genesis{ BaseFee: big.NewInt(params.InitialBaseFee), - }).MustCommit(db) - blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) + Config: params.TestChainConfig, + } + genesis := gspec.MustCommit(db) + blocks, _ := GenerateChain(gspec.Config, genesis, engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) // Generate a bunch of fork blocks, each side forking from the canonical chain forks := make([]*types.Block, len(blocks)) @@ -1289,17 +1293,14 @@ func TestTrieForkGC(t *testing.T) { if i > 0 { parent = blocks[i-1] } - fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) + fork, _ := GenerateChain(gspec.Config, parent, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) forks[i] = fork[0] } // Import the canonical and fork chain side by side, forcing the trie cache to cache both diskdb := rawdb.NewMemoryDatabase() - (&Genesis{ - Config: params.TestChainConfig, - BaseFee: big.NewInt(params.InitialBaseFee), - }).MustCommit(diskdb) + gspec.MustCommit(diskdb) - chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) + chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -1327,22 +1328,22 @@ func TestLargeReorgTrieGC(t *testing.T) { // Generate the original common chain segment and the two competing forks engine := ethash.NewFaker() gspec := &Genesis{ - Config: params.TestChainConfig, BaseFee: big.NewInt(params.InitialBaseFee), + Config: params.TestChainConfig, } db := rawdb.NewMemoryDatabase() genesis := gspec.MustCommit(db) - shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) - original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) - competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*triesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) + shared, _ := GenerateChain(gspec.Config, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) + original, _ := GenerateChain(gspec.Config, shared[len(shared)-1], engine, db, 2*triesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) + competitor, _ := GenerateChain(gspec.Config, shared[len(shared)-1], engine, db, 2*triesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) }) // Import the shared chain and the original canonical one diskdb := rawdb.NewMemoryDatabase() gspec.MustCommit(diskdb) - chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) + chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -1385,8 +1386,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) bankFunds = big.NewInt(100000000000000000) - gspec = Genesis{ - Config: params.TestChainConfig, + gspec = &Genesis{ Alloc: GenesisAlloc{ testBankAddress: {Balance: bankFunds}, common.HexToAddress("0xc0de"): { @@ -1394,6 +1394,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in Balance: big.NewInt(0), }, // push 1, pop }, + Config: params.TestChainConfig, GasLimit: 100e6, // 100 M } ) @@ -1416,7 +1417,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in } } - shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, numBlocks, blockGenerator) + shared, _ := GenerateChain(gspec.Config, genesis, engine, db, numBlocks, blockGenerator) b.StopTimer() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -1424,7 +1425,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in diskdb := rawdb.NewMemoryDatabase() gspec.MustCommit(diskdb) - chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) + chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}) if err != nil { b.Fatalf("failed to create tester chain: %v", err) } @@ -1710,10 +1711,10 @@ func TestTransientStorageReset(t *testing.T) { byte(vm.RETURN), // return 6 bytes of zero-code }...) gspec := &Genesis{ - Config: params.TestChainConfig, Alloc: types.GenesisAlloc{ address: {Balance: funds}, }, + Config: params.TestChainConfig, } nonce := uint64(0) signer := types.HomesteadSigner{} @@ -1781,7 +1782,6 @@ func TestEIP3651(t *testing.T) { addr2 = crypto.PubkeyToAddress(key2.PublicKey) funds = big.NewInt(8000000000000000) gspec = &Genesis{ - Config: params.TestChainConfig, Alloc: types.GenesisAlloc{ addr1: {Balance: funds}, addr2: {Balance: funds}, @@ -1813,6 +1813,7 @@ func TestEIP3651(t *testing.T) { Balance: big.NewInt(0), }, }, + Config: params.TestChainConfig, } ) @@ -1899,7 +1900,6 @@ func TestDeleteCreateRevert(t *testing.T) { address = crypto.PubkeyToAddress(key.PublicKey) funds = big.NewInt(10000000000000000) gspec = &Genesis{ - Config: params.TestChainConfig, Alloc: GenesisAlloc{ address: {Balance: funds}, // The address 0xAAAAA selfdestructs if called @@ -1925,11 +1925,12 @@ func TestDeleteCreateRevert(t *testing.T) { Balance: big.NewInt(1), }, }, + Config: params.TestChainConfig, } genesis = gspec.MustCommit(db) ) - blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 1, func(i int, b *BlockGen) { + blocks, _ := GenerateChain(gspec.Config, genesis, engine, db, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) // One transaction to AAAA tx, _ := types.SignTx(types.NewTransaction(0, aa, @@ -1944,7 +1945,7 @@ func TestDeleteCreateRevert(t *testing.T) { diskdb := rawdb.NewMemoryDatabase() gspec.MustCommit(diskdb) - chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}) + chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } diff --git a/core/chain_makers.go b/core/chain_makers.go index ebbd60a043..3b0e667110 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -272,7 +272,7 @@ func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, if err != nil { panic(err) } - blocks, receipts := GenerateChain(genesis.Config, genesis.ToBlock(nil), engine, db, n, gen) + blocks, receipts := GenerateChain(genesis.Config, genesis.ToBlock(), engine, db, n, gen) return db, blocks, receipts } diff --git a/core/dao_test.go b/core/dao_test.go index 8bb3bfa55f..3885f5cfb7 100644 --- a/core/dao_test.go +++ b/core/dao_test.go @@ -38,7 +38,7 @@ func TestDAOForkRangeExtradata(t *testing.T) { } db := rawdb.NewMemoryDatabase() genesis := gspec.MustCommit(db) - prefix, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {}) + prefix, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {}) // Create the concurrent, conflicting two nodes proDb := rawdb.NewMemoryDatabase() diff --git a/core/genesis.go b/core/genesis.go index d01f86312c..b84859d5e6 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -99,6 +99,63 @@ func getGenesisState(db ethdb.Database, blockhash common.Hash) (alloc types.Gene return nil, nil } +// hashAlloc computes the state root according to the genesis specification. +func hashAlloc(ga *types.GenesisAlloc) (common.Hash, error) { + // Create an ephemeral in-memory database for computing hash, + // all the derived states will be discarded to not pollute disk. + db := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), nil) + statedb, err := state.New(types.EmptyRootHash, db) + if err != nil { + return common.Hash{}, err + } + for addr, account := range *ga { + if account.Balance != nil { + statedb.AddBalance(addr, account.Balance, tracing.BalanceIncreaseGenesisBalance) + } + statedb.SetCode(addr, account.Code) + statedb.SetNonce(addr, account.Nonce) + for key, value := range account.Storage { + statedb.SetState(addr, key, value) + } + } + return statedb.Commit(0, false) +} + +// flushAlloc is very similar to hashAlloc, but the main difference is +// all the generated states will be persisted into the given database. +// Also, the genesis state specification will be flushed as well. +func flushAlloc(ga *types.GenesisAlloc, db ethdb.Database, blockhash common.Hash) error { + statedb, err := state.New(types.EmptyRootHash, state.NewDatabase(db)) + if err != nil { + return err + } + for addr, account := range *ga { + if account.Balance != nil { + statedb.AddBalance(addr, account.Balance, tracing.BalanceIncreaseGenesisBalance) + } + statedb.SetCode(addr, account.Code) + statedb.SetNonce(addr, account.Nonce) + for key, value := range account.Storage { + statedb.SetState(addr, key, value) + } + } + root, err := statedb.Commit(0, false) + if err != nil { + return err + } + err = statedb.Database().TrieDB().Commit(root, true) + if err != nil { + return err + } + // Marshal the genesis state specification and persist. + blob, err := json.Marshal(ga) + if err != nil { + return err + } + rawdb.WriteGenesisStateSpec(db, blockhash, blob) + return nil +} + // field type overrides for gencodec type genesisSpecMarshaling struct { Nonce math.HexOrDecimal64 @@ -181,7 +238,7 @@ func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig // Check whether the genesis block is already written. if genesis != nil { - hash := genesis.ToBlock(nil).Hash() + hash := genesis.ToBlock().Hash() if hash != stored { return genesis.Config, hash, &GenesisMismatchError{stored, hash} } @@ -248,22 +305,12 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig { } } -// ToBlock creates the genesis block and writes state of a genesis specification -// to the given database (or discards it if nil). -func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { - if db == nil { - db = rawdb.NewMemoryDatabase() +// ToBlock returns the genesis block according to genesis specification. +func (g *Genesis) ToBlock() *types.Block { + root, err := hashAlloc(&g.Alloc) + if err != nil { + panic(err) } - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(db)) - for addr, account := range g.Alloc { - statedb.AddBalance(addr, account.Balance, tracing.BalanceIncreaseGenesisBalance) - statedb.SetCode(addr, account.Code) - statedb.SetNonce(addr, account.Nonce) - for key, value := range account.Storage { - statedb.SetState(addr, key, value) - } - } - root := statedb.IntermediateRoot(false) head := &types.Header{ Number: new(big.Int).SetUint64(g.Number), Nonce: types.EncodeNonce(g.Nonce), @@ -284,7 +331,6 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { if g.Difficulty == nil { head.Difficulty = params.GenesisDifficulty } - // Notice: Eip1559Block affects the block hash, we must set: // 1. g.Config.Eip1559Block // 2. or common.Eip1559Block @@ -295,30 +341,29 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee) } } - - statedb.Commit(0, false) - statedb.Database().TrieDB().Commit(root, true) - return types.NewBlock(head, nil, nil, trie.NewStackTrie(nil)) } // Commit writes the block and state of a genesis specification to the database. // The block is committed as the canonical head block. func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { - if g.Number != 0 { + block := g.ToBlock() + if block.Number().Sign() != 0 { return nil, errors.New("can't commit genesis block with number > 0") } config := g.Config - // if config == nil { - // config = params.AllEthashProtocolChanges - // } if config == nil { return nil, errors.New("invalid genesis without chain config") } if config.XDPoS != nil && len(g.ExtraData) < 32+crypto.SignatureLength { return nil, errors.New("can't start XDPoS chain without signers") } - block := g.ToBlock(db) + // All the checks have passed, flushAlloc the states derived from the genesis + // specification as well as the specification itself into the provided + // database. + if err := flushAlloc(&g.Alloc, db, block.Hash()); err != nil { + return nil, err + } batch := db.NewBatch() rawdb.WriteTd(batch, block.Hash(), block.NumberU64(), g.Difficulty) rawdb.WriteBlock(batch, block) @@ -341,16 +386,6 @@ func (g *Genesis) MustCommit(db ethdb.Database) *types.Block { return block } -// GenesisBlockForTesting creates and writes a block in which addr has the given wei balance. -func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block { - g := Genesis{ - Config: params.TestChainConfig, - Alloc: types.GenesisAlloc{addr: {Balance: balance}}, - BaseFee: big.NewInt(params.InitialBaseFee), - } - return g.MustCommit(db) -} - // DefaultGenesisBlock returns the XDC mainnet genesis block. func DefaultGenesisBlock() *Genesis { return &Genesis{ diff --git a/core/genesis_test.go b/core/genesis_test.go index 83d4da1626..a033df23b0 100644 --- a/core/genesis_test.go +++ b/core/genesis_test.go @@ -34,11 +34,11 @@ import ( ) func TestDefaultGenesisBlock(t *testing.T) { - block := DefaultGenesisBlock().ToBlock(nil) + block := DefaultGenesisBlock().ToBlock() if block.Hash() != params.MainnetGenesisHash { t.Errorf("wrong mainnet genesis hash, got %v, want %v", block.Hash().String(), params.MainnetGenesisHash.String()) } - block = DefaultTestnetGenesisBlock().ToBlock(nil) + block = DefaultTestnetGenesisBlock().ToBlock() if block.Hash() != params.TestnetGenesisHash { t.Errorf("wrong testnet genesis hash, got %v, want %v", block.Hash().String(), params.TestnetGenesisHash.String()) } diff --git a/core/rawdb/accessors_metadata.go b/core/rawdb/accessors_metadata.go index bd2a8f9b34..efb6b0c683 100644 --- a/core/rawdb/accessors_metadata.go +++ b/core/rawdb/accessors_metadata.go @@ -19,6 +19,7 @@ package rawdb import ( "encoding/json" "errors" + "fmt" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/ethdb" @@ -62,7 +63,8 @@ func ReadChainConfig(db ethdb.KeyValueReader, hash common.Hash) (*params.ChainCo var config params.ChainConfig if err := json.Unmarshal(jsonChainConfig, &config); err != nil { - return nil, err + log.Error("Invalid chain config JSON", "hash", hash, "err", err) + return nil, fmt.Errorf("invalid chain config JSON for hash %s: %w", hash.Hex(), err) } return &config, nil @@ -88,3 +90,10 @@ func ReadGenesisStateSpec(db ethdb.KeyValueReader, blockhash common.Hash) []byte data, _ := db.Get(genesisStateSpecKey(blockhash)) return data } + +// WriteGenesisStateSpec writes the genesis state specification into the disk. +func WriteGenesisStateSpec(db ethdb.KeyValueWriter, blockhash common.Hash, data []byte) { + if err := db.Put(genesisStateSpecKey(blockhash), data); err != nil { + log.Crit("Failed to store genesis state", "err", err) + } +} diff --git a/eth/downloader/queue_test.go b/eth/downloader/queue_test.go index f20e4af39d..3d0fdd7f01 100644 --- a/eth/downloader/queue_test.go +++ b/eth/downloader/queue_test.go @@ -29,23 +29,17 @@ import ( "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/consensus/ethash" "github.com/XinFinOrg/XDPoSChain/core" - "github.com/XinFinOrg/XDPoSChain/core/rawdb" "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/log" "github.com/XinFinOrg/XDPoSChain/params" ) -var ( - testdb = rawdb.NewMemoryDatabase() - genesis = core.GenesisBlockForTesting(testdb, testAddress, big.NewInt(1000000000)) -) - // makeChain creates a chain of n blocks starting at and including parent. // the returned hash chain is ordered head->parent. In addition, every 3rd block // contains a transaction and every 5th an uncle to allow testing correct block // reassembly. func makeChain(n int, seed byte, parent *types.Block, empty bool) ([]*types.Block, []types.Receipts) { - blocks, receipts := core.GenerateChain(params.TestChainConfig, parent, ethash.NewFaker(), testdb, n, func(i int, block *core.BlockGen) { + blocks, receipts := core.GenerateChain(params.TestChainConfig, parent, ethash.NewFaker(), testDB, n, func(i int, block *core.BlockGen) { block.SetCoinbase(common.Address{seed}) // Add one tx to every secondblock if !empty && i%2 == 0 { @@ -71,10 +65,10 @@ var emptyChain *chainData func init() { // Create a chain of blocks to import targetBlocks := 128 - blocks, _ := makeChain(targetBlocks, 0, genesis, false) + blocks, _ := makeChain(targetBlocks, 0, testGenesis, false) chain = &chainData{blocks, 0} - blocks, _ = makeChain(targetBlocks, 0, genesis, true) + blocks, _ = makeChain(targetBlocks, 0, testGenesis, true) emptyChain = &chainData{blocks, 0} } @@ -235,7 +229,7 @@ func TestEmptyBlocks(t *testing.T) { // some more advanced scenarios func XTestDelivery(t *testing.T) { // the outside network, holding blocks - blo, rec := makeChain(128, 0, genesis, false) + blo, rec := makeChain(128, 0, testGenesis, false) world := newNetwork() world.receipts = rec world.chain = blo diff --git a/eth/downloader/testchain_test.go b/eth/downloader/testchain_test.go index b1a0c403d5..c75ead7b08 100644 --- a/eth/downloader/testchain_test.go +++ b/eth/downloader/testchain_test.go @@ -20,6 +20,7 @@ import ( "fmt" "math/big" "sync" + "time" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/consensus/ethash" @@ -35,18 +36,33 @@ var ( testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") testAddress = crypto.PubkeyToAddress(testKey.PublicKey) testDB = rawdb.NewMemoryDatabase() - testGenesis = core.GenesisBlockForTesting(testDB, testAddress, big.NewInt(1000000000000000000)) + + testGspec = core.Genesis{ + Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000000)}}, + BaseFee: big.NewInt(params.InitialBaseFee), + Config: params.TestChainConfig, + } + testGenesis = testGspec.MustCommit(testDB) ) // The common prefix of all test chains: -var testChainBase = newTestChain(blockCacheMaxItems+200, testGenesis) +var testChainBase *testChain // Different forks on top of the base chain: var testChainForkLightA, testChainForkLightB, testChainForkHeavy *testChain func init() { + // Reduce some of the parameters to make the tester faster + blockCacheMaxItems = 1024 + fsHeaderSafetyNet = 256 + fsHeaderContCheck = 500 * time.Millisecond + + testChainBase = newTestChain(blockCacheMaxItems+200, testGenesis) + var forkLen = int(MaxForkAncestry + 50) var wg sync.WaitGroup + + // Generate the test chains to seed the peers with wg.Go(func() { testChainForkLightA = testChainBase.makeFork(forkLen, false, 1) }) wg.Go(func() { testChainForkLightB = testChainBase.makeFork(forkLen, false, 2) }) wg.Go(func() { testChainForkHeavy = testChainBase.makeFork(forkLen, true, 3) }) diff --git a/eth/fetcher/fetcher_test.go b/eth/fetcher/fetcher_test.go index f665338165..7c887af980 100644 --- a/eth/fetcher/fetcher_test.go +++ b/eth/fetcher/fetcher_test.go @@ -36,10 +36,17 @@ import ( ) var ( - testdb = rawdb.NewMemoryDatabase() - testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - testAddress = crypto.PubkeyToAddress(testKey.PublicKey) - genesis = core.GenesisBlockForTesting(testdb, testAddress, big.NewInt(1000000000)) + testdb = rawdb.NewMemoryDatabase() + testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + testAddress = crypto.PubkeyToAddress(testKey.PublicKey) + + gspec = core.Genesis{ + Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000)}}, + BaseFee: big.NewInt(params.InitialBaseFee), + Config: params.TestChainConfig, + } + genesis = gspec.MustCommit(testdb) + unknownBlock = types.NewBlock(&types.Header{Root: types.EmptyRootHash, GasLimit: params.GenesisGasLimit}, nil, nil, trie.NewStackTrie(nil)) ) diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index bf01ef9aa4..74ef8b7598 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -189,11 +189,12 @@ func TestBlockSubscription(t *testing.T) { db = rawdb.NewMemoryDatabase() backend, sys = newTestFilterSystem(t, db, Config{}) api = NewFilterAPI(sys, false) - genesis = (&core.Genesis{ - Config: params.TestChainConfig, + gspec = &core.Genesis{ BaseFee: big.NewInt(params.InitialBaseFee), - }).MustCommit(db) - chain, _ = core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 10, func(i int, gen *core.BlockGen) {}) + Config: params.TestChainConfig, + } + genesis = gspec.MustCommit(db) + chain, _ = core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 10, func(i int, gen *core.BlockGen) {}) chainEvents = []core.ChainEvent{} ) @@ -793,10 +794,11 @@ func TestLightFilterLogs(t *testing.T) { key, _ = crypto.GenerateKey() addr = crypto.PubkeyToAddress(key.PublicKey) - genesis = &core.Genesis{Config: params.TestChainConfig, + genesis = &core.Genesis{ Alloc: types.GenesisAlloc{ addr: {Balance: big.NewInt(params.Ether)}, }, + Config: params.TestChainConfig, } receipts = []*types.Receipt{{ Logs: []*types.Log{allLogs[0]}, diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go index b14c78bc3e..64f248f04a 100644 --- a/eth/filters/filter_test.go +++ b/eth/filters/filter_test.go @@ -56,11 +56,19 @@ func BenchmarkFilters(b *testing.B) { addr2 = common.BytesToAddress([]byte("jeff")) addr3 = common.BytesToAddress([]byte("ethereum")) addr4 = common.BytesToAddress([]byte("random addresses please")) + + gspec = core.Genesis{ + Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}}, + BaseFee: big.NewInt(params.InitialBaseFee), + Config: params.TestChainConfig, + } + genesis = gspec.ToBlock() ) defer db.Close() - genesis := core.GenesisBlockForTesting(db, addr1, big.NewInt(1000000)) - chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 100010, func(i int, gen *core.BlockGen) { + gspec.MustCommit(db) + + chain, receipts := core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 100010, func(i int, gen *core.BlockGen) { switch i { case 2403: receipt := makeReceipt(addr1) @@ -162,16 +170,17 @@ func TestFilters(t *testing.T) { }, BaseFee: big.NewInt(params.InitialBaseFee), } + genesis = gspec.ToBlock() ) + defer db.Close() + + gspec.MustCommit(db) contractABI, err := abi.JSON(strings.NewReader(abiStr)) if err != nil { t.Fatal(err) } - // Hack: GenerateChainWithGenesis creates a new db. - // Commit the genesis manually and use GenerateChain. - genesis := gspec.MustCommit(db) chain, _ := core.GenerateChain(&config, genesis, ethash.NewFaker(), db, 1000, func(i int, gen *core.BlockGen) { switch i { case 1: @@ -357,9 +366,9 @@ func TestRangeLimit(t *testing.T) { defer db.Close() gspec := &core.Genesis{ - Config: params.TestChainConfig, Alloc: types.GenesisAlloc{}, BaseFee: big.NewInt(params.InitialBaseFee), + Config: params.TestChainConfig, } genesis := gspec.MustCommit(db) chain, _ := core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 10, func(i int, gen *core.BlockGen) {}) diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go index da4d4329a0..7fe557d6be 100644 --- a/eth/gasprice/gasprice_test.go +++ b/eth/gasprice/gasprice_test.go @@ -122,7 +122,7 @@ func newTestBackend(t *testing.T, eip1559Block *big.Int, pending bool) *testBack ) engine := ethash.NewFaker() db := rawdb.NewMemoryDatabase() - genesis, _ := gspec.Commit(db) + genesis := gspec.MustCommit(db) // Generate testing blocks blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, db, testHead+1, func(i int, b *core.BlockGen) { @@ -153,7 +153,7 @@ func newTestBackend(t *testing.T, eip1559Block *big.Int, pending bool) *testBack }) // Construct testing chain diskdb := rawdb.NewMemoryDatabase() - gspec.Commit(diskdb) + gspec.MustCommit(diskdb) chain, err := core.NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}) if err != nil { t.Fatalf("Failed to create local chain, %v", err) diff --git a/eth/helper_test.go b/eth/helper_test.go index 0e29afa2a8..191d32deeb 100644 --- a/eth/helper_test.go +++ b/eth/helper_test.go @@ -58,8 +58,8 @@ func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func engine = ethash.NewFaker() db = rawdb.NewMemoryDatabase() gspec = &core.Genesis{ - Config: params.TestChainConfig, Alloc: types.GenesisAlloc{testBank: {Balance: big.NewInt(1000000)}}, + Config: params.TestChainConfig, } genesis = gspec.MustCommit(db) blockchain, _ = core.NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}) diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index 948563e36c..6935448fae 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -846,13 +846,12 @@ func TestTraceCallBlockSigners(t *testing.T) { // Initialize test accounts accounts := newAccounts(1) - config := *params.TestChainConfig genesis := &core.Genesis{ - Config: &config, Alloc: types.GenesisAlloc{ accounts[0].addr: {Balance: big.NewInt(params.Ether)}, common.BlockSignersBinary: {Balance: big.NewInt(0)}, // System contract }, + Config: params.TestChainConfig, } backend := newTestBackend(t, 1, genesis, func(i int, b *core.BlockGen) { // Just create an empty block @@ -913,13 +912,12 @@ func TestTraceCallBlockSignersNonceValidation(t *testing.T) { // Initialize test accounts accounts := newAccounts(1) - config := *params.TestChainConfig genesis := &core.Genesis{ - Config: &config, Alloc: types.GenesisAlloc{ accounts[0].addr: {Balance: big.NewInt(params.Ether), Nonce: 5}, // Account has nonce 5 common.BlockSignersBinary: {Balance: big.NewInt(0)}, // System contract }, + Config: params.TestChainConfig, } backend := newTestBackend(t, 1, genesis, func(i int, b *core.BlockGen) { // Just create an empty block diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 212089d857..350e18556a 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -158,7 +158,7 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) (*state.StateD if !ok { return nil, UnsupportedForkError{subtest.Fork} } - block := t.genesis(config).ToBlock(nil) + block := t.genesis(config).ToBlock() db := rawdb.NewMemoryDatabase() statedb := MakePreState(db, t.json.Pre)