core: improve commit genesis

This commit is contained in:
Daniel Liu 2025-03-20 12:48:04 +08:00
parent b7eeb0d939
commit 6285a4fe05
5 changed files with 85 additions and 46 deletions

View file

@ -26,15 +26,50 @@ import (
"time"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/consensus"
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/core/state"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/core/vm"
"github.com/XinFinOrg/XDPoSChain/crypto"
"github.com/XinFinOrg/XDPoSChain/ethdb"
"github.com/XinFinOrg/XDPoSChain/params"
)
// newCanonical creates a chain database, and injects a deterministic canonical
// chain. Depending on the full flag, it creates either a full block chain or a
// header only chain. The database and genesis specification for block generation
// are also returned in case more test blocks are needed later.
func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *BlockChain, error) {
var (
gspec = &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.AllEthashProtocolChanges,
}
)
db := rawdb.NewMemoryDatabase()
genesis := gspec.MustCommit(db)
// Initialize a fresh chain with only a genesis block
blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{})
// Create and inject the requested chain
if n == 0 {
return db, blockchain, nil
}
if full {
// Full block-chain requested
blocks := makeBlockChain(genesis, n, engine, db, canonicalSeed)
_, err := blockchain.InsertChain(blocks)
return db, blockchain, err
}
// Header-only chain requested
headers := makeHeaderChain(genesis.Header(), n, engine, db, canonicalSeed)
_, err := blockchain.InsertHeaderChain(headers, 1)
return db, blockchain, err
}
// Test fork of length N starting from block i
func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, comparator func(td1, td2 *big.Int)) {
// Copy old chain up to #i into a new db
@ -1192,7 +1227,11 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
engine := ethash.NewFaker()
db := rawdb.NewMemoryDatabase()
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
gspec := &Genesis{
Config: params.TestChainConfig,
BaseFee: big.NewInt(params.InitialBaseFee),
}
genesis := gspec.MustCommit(db)
blocks, _ := GenerateChain(params.TestChainConfig, 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
@ -1208,7 +1247,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
// Import the canonical and fork chain side by side, verifying the current block
// and current header consistency
diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb)
gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{})
if err != nil {
@ -1237,7 +1276,10 @@ func TestTrieForkGC(t *testing.T) {
engine := ethash.NewFaker()
db := rawdb.NewMemoryDatabase()
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
genesis := (&Genesis{
Config: params.TestChainConfig,
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}) })
// Generate a bunch of fork blocks, each side forking from the canonical chain
@ -1252,7 +1294,10 @@ func TestTrieForkGC(t *testing.T) {
}
// Import the canonical and fork chain side by side, forcing the trie cache to cache both
diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb)
(&Genesis{
Config: params.TestChainConfig,
BaseFee: big.NewInt(params.InitialBaseFee),
}).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{})
if err != nil {
@ -1281,9 +1326,13 @@ func TestTrieForkGC(t *testing.T) {
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),
}
db := rawdb.NewMemoryDatabase()
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
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}) })
@ -1291,7 +1340,7 @@ func TestLargeReorgTrieGC(t *testing.T) {
// Import the shared chain and the original canonical one
diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb)
gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{})
if err != nil {

View file

@ -304,32 +304,6 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
return header
}
// newCanonical creates a chain database, and injects a deterministic canonical
// chain. Depending on the full flag, if creates either a full block chain or a
// header only chain.
func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *BlockChain, error) {
// Initialize a fresh chain with only a genesis block
gspec := new(Genesis)
db := rawdb.NewMemoryDatabase()
genesis := gspec.MustCommit(db)
blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{})
// Create and inject the requested chain
if n == 0 {
return db, blockchain, nil
}
if full {
// Full block-chain requested
blocks := makeBlockChain(genesis, n, engine, db, canonicalSeed)
_, err := blockchain.InsertChain(blocks)
return db, blockchain, err
}
// Header-only chain requested
headers := makeHeaderChain(genesis.Header(), n, engine, db, canonicalSeed)
_, err := blockchain.InsertHeaderChain(headers, 1)
return db, blockchain, err
}
// makeHeaderChain creates a deterministic chain of headers rooted at parent.
func makeHeaderChain(parent *types.Header, n int, engine consensus.Engine, db ethdb.Database, seed int) []*types.Header {
blocks := makeBlockChain(types.NewBlockWithHeader(parent), n, engine, db, seed)

View file

@ -32,8 +32,11 @@ func TestDAOForkRangeExtradata(t *testing.T) {
forkBlock := big.NewInt(32)
// Generate a common prefix for both pro-forkers and non-forkers
gspec := &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.TestChainConfig,
}
db := rawdb.NewMemoryDatabase()
gspec := &Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}
genesis := gspec.MustCommit(db)
prefix, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {})

View file

@ -234,21 +234,30 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
// 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) {
block := g.ToBlock(db)
if block.Number().Sign() != 0 {
if g.Number != 0 {
return nil, errors.New("can't commit genesis block with number > 0")
}
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), g.Difficulty)
rawdb.WriteBlock(db, block)
rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil)
rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64())
rawdb.WriteHeadBlockHash(db, block.Hash())
rawdb.WriteHeadHeaderHash(db, block.Hash())
config := g.Config
// if config == nil {
// config = params.AllEthashProtocolChanges
// }
if config == nil {
config = params.AllEthashProtocolChanges
return nil, errors.New("invalid genesis without chain config")
}
return block, rawdb.WriteChainConfig(db, block.Hash(), 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)
batch := db.NewBatch()
rawdb.WriteTd(batch, block.Hash(), block.NumberU64(), g.Difficulty)
rawdb.WriteBlock(batch, block)
rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), nil)
rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64())
rawdb.WriteHeadBlockHash(batch, block.Hash())
rawdb.WriteHeadFastBlockHash(batch, block.Hash())
rawdb.WriteHeadHeaderHash(batch, block.Hash())
rawdb.WriteChainConfig(db, block.Hash(), config)
return block, batch.Write()
}
// MustCommit writes the genesis block and state to db, panicking on error.
@ -264,6 +273,7 @@ func (g *Genesis) MustCommit(db ethdb.Database) *types.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),
}

View file

@ -187,9 +187,12 @@ func TestBlockSubscription(t *testing.T) {
db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{})
api = NewFilterAPI(sys, false)
genesis = (&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) {})
chainEvents = []core.ChainEvent{}
genesis = (&core.Genesis{
Config: params.TestChainConfig,
BaseFee: big.NewInt(params.InitialBaseFee),
}).MustCommit(db)
chain, _ = core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 10, func(i int, gen *core.BlockGen) {})
chainEvents = []core.ChainEvent{}
)
for _, blk := range chain {