Merge pull request #922 from gzliudan/commit-genesis

core: improve commit genesis
This commit is contained in:
Daniel Liu 2025-03-20 22:22:28 +08:00 committed by GitHub
commit 9c144eee05
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 85 additions and 46 deletions

View file

@ -26,15 +26,50 @@ import (
"time" "time"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/consensus"
"github.com/XinFinOrg/XDPoSChain/consensus/ethash" "github.com/XinFinOrg/XDPoSChain/consensus/ethash"
"github.com/XinFinOrg/XDPoSChain/core/rawdb" "github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/core/state" "github.com/XinFinOrg/XDPoSChain/core/state"
"github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/core/vm" "github.com/XinFinOrg/XDPoSChain/core/vm"
"github.com/XinFinOrg/XDPoSChain/crypto" "github.com/XinFinOrg/XDPoSChain/crypto"
"github.com/XinFinOrg/XDPoSChain/ethdb"
"github.com/XinFinOrg/XDPoSChain/params" "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 // 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)) { 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 // Copy old chain up to #i into a new db
@ -1192,7 +1227,11 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := rawdb.NewMemoryDatabase() 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}) }) 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 // 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 // Import the canonical and fork chain side by side, verifying the current block
// and current header consistency // and current header consistency
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
(&Genesis{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, params.TestChainConfig, engine, vm.Config{})
if err != nil { if err != nil {
@ -1237,7 +1276,10 @@ func TestTrieForkGC(t *testing.T) {
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := rawdb.NewMemoryDatabase() 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}) }) 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 // 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 // Import the canonical and fork chain side by side, forcing the trie cache to cache both
diskdb := rawdb.NewMemoryDatabase() 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{}) chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{})
if err != nil { if err != nil {
@ -1281,9 +1326,13 @@ func TestTrieForkGC(t *testing.T) {
func TestLargeReorgTrieGC(t *testing.T) { func TestLargeReorgTrieGC(t *testing.T) {
// Generate the original common chain segment and the two competing forks // Generate the original common chain segment and the two competing forks
engine := ethash.NewFaker() engine := ethash.NewFaker()
gspec := &Genesis{
Config: params.TestChainConfig,
BaseFee: big.NewInt(params.InitialBaseFee),
}
db := rawdb.NewMemoryDatabase() 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}) }) 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}) }) 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 // Import the shared chain and the original canonical one
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
(&Genesis{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, params.TestChainConfig, engine, vm.Config{})
if err != nil { if err != nil {

View file

@ -304,32 +304,6 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
return header 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. // 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 { 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) blocks := makeBlockChain(types.NewBlockWithHeader(parent), n, engine, db, seed)

View file

@ -32,8 +32,11 @@ func TestDAOForkRangeExtradata(t *testing.T) {
forkBlock := big.NewInt(32) forkBlock := big.NewInt(32)
// Generate a common prefix for both pro-forkers and non-forkers // Generate a common prefix for both pro-forkers and non-forkers
gspec := &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.TestChainConfig,
}
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
gspec := &Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}
genesis := gspec.MustCommit(db) genesis := gspec.MustCommit(db)
prefix, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {}) 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. // Commit writes the block and state of a genesis specification to the database.
// The block is committed as the canonical head block. // The block is committed as the canonical head block.
func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
block := g.ToBlock(db) if g.Number != 0 {
if block.Number().Sign() != 0 {
return nil, errors.New("can't commit genesis block with 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 config := g.Config
// if config == nil {
// config = params.AllEthashProtocolChanges
// }
if config == nil { 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. // 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. // 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 { func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block {
g := Genesis{ g := Genesis{
Config: params.TestChainConfig,
Alloc: types.GenesisAlloc{addr: {Balance: balance}}, Alloc: types.GenesisAlloc{addr: {Balance: balance}},
BaseFee: big.NewInt(params.InitialBaseFee), BaseFee: big.NewInt(params.InitialBaseFee),
} }

View file

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