mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
add state variable to verifyHeader(), verifyHeaders() in the consensus interface
This commit is contained in:
parent
c7144977e4
commit
206fcfd8b6
10 changed files with 86 additions and 62 deletions
|
|
@ -33,7 +33,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/fdlimit"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||
//"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||
"github.com/ethereum/go-ethereum/consensus/posv"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
|
|
@ -1245,17 +1245,18 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai
|
|||
if config.Posv != nil {
|
||||
engine = posv.New(config.Posv, chainDb)
|
||||
} else {
|
||||
engine = ethash.NewFaker()
|
||||
if !ctx.GlobalBool(FakePoWFlag.Name) {
|
||||
engine = ethash.New(ethash.Config{
|
||||
CacheDir: stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir),
|
||||
CachesInMem: eth.DefaultConfig.Ethash.CachesInMem,
|
||||
CachesOnDisk: eth.DefaultConfig.Ethash.CachesOnDisk,
|
||||
DatasetDir: stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir),
|
||||
DatasetsInMem: eth.DefaultConfig.Ethash.DatasetsInMem,
|
||||
DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk,
|
||||
})
|
||||
}
|
||||
//engine = ethash.NewFaker()
|
||||
//if !ctx.GlobalBool(FakePoWFlag.Name) {
|
||||
// engine = ethash.New(ethash.Config{
|
||||
// CacheDir: stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir),
|
||||
// CachesInMem: eth.DefaultConfig.Ethash.CachesInMem,
|
||||
// CachesOnDisk: eth.DefaultConfig.Ethash.CachesOnDisk,
|
||||
// DatasetDir: stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir),
|
||||
// DatasetsInMem: eth.DefaultConfig.Ethash.DatasetsInMem,
|
||||
// DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk,
|
||||
// })
|
||||
//}
|
||||
Fatalf("Only support posv consensus")
|
||||
}
|
||||
if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
|
||||
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
|
||||
|
|
|
|||
|
|
@ -58,13 +58,13 @@ type Engine interface {
|
|||
// VerifyHeader checks whether a header conforms to the consensus rules of a
|
||||
// given engine. Verifying the seal may be done optionally here, or explicitly
|
||||
// via the VerifySeal method.
|
||||
VerifyHeader(chain ChainReader, header *types.Header, fullVerify bool) error
|
||||
VerifyHeader(chain ChainReader, state *state.StateDB, header *types.Header, fullVerify bool) error
|
||||
|
||||
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
|
||||
// concurrently. The method returns a quit channel to abort the operations and
|
||||
// a results channel to retrieve the async verifications (the order is that of
|
||||
// the input slice).
|
||||
VerifyHeaders(chain ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error)
|
||||
VerifyHeaders(chain ChainReader, state *state.StateDB, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error)
|
||||
|
||||
// VerifyUncles verifies that the given block's uncles conform to the consensus
|
||||
// rules of a given engine.
|
||||
|
|
@ -76,7 +76,7 @@ type Engine interface {
|
|||
|
||||
// Prepare initializes the consensus fields of a block header according to the
|
||||
// rules of a particular engine. The changes are executed inline.
|
||||
Prepare(chain ChainReader, header *types.Header) error
|
||||
Prepare(chain ChainReader, state *state.StateDB, header *types.Header) error
|
||||
|
||||
// Finalize runs any post-transaction state modifications (e.g. block rewards)
|
||||
// and assembles the final block.
|
||||
|
|
|
|||
|
|
@ -261,20 +261,20 @@ func (c *Posv) Author(header *types.Header) (common.Address, error) {
|
|||
}
|
||||
|
||||
// VerifyHeader checks whether a header conforms to the consensus rules.
|
||||
func (c *Posv) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error {
|
||||
return c.verifyHeaderWithCache(chain, header, nil, fullVerify)
|
||||
func (c *Posv) VerifyHeader(chain consensus.ChainReader, state *state.StateDB, header *types.Header, fullVerify bool) error {
|
||||
return c.verifyHeaderWithCache(chain, state, header, nil, fullVerify)
|
||||
}
|
||||
|
||||
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The
|
||||
// method returns a quit channel to abort the operations and a results channel to
|
||||
// retrieve the async verifications (the order is that of the input slice).
|
||||
func (c *Posv) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) {
|
||||
func (c *Posv) VerifyHeaders(chain consensus.ChainReader, state *state.StateDB, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) {
|
||||
abort := make(chan struct{})
|
||||
results := make(chan error, len(headers))
|
||||
|
||||
go func() {
|
||||
for i, header := range headers {
|
||||
err := c.verifyHeaderWithCache(chain, header, headers[:i], fullVerifies[i])
|
||||
err := c.verifyHeaderWithCache(chain, state, header, headers[:i], fullVerifies[i])
|
||||
|
||||
select {
|
||||
case <-abort:
|
||||
|
|
@ -286,12 +286,12 @@ func (c *Posv) VerifyHeaders(chain consensus.ChainReader, headers []*types.Heade
|
|||
return abort, results
|
||||
}
|
||||
|
||||
func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||
func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, state *state.StateDB, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||
_, check := c.verifiedHeaders.Get(header.Hash())
|
||||
if check {
|
||||
return nil
|
||||
}
|
||||
err := c.verifyHeader(chain, header, parents, fullVerify)
|
||||
err := c.verifyHeader(chain, state, header, parents, fullVerify)
|
||||
if err == nil {
|
||||
c.verifiedHeaders.Add(header.Hash(), true)
|
||||
}
|
||||
|
|
@ -302,7 +302,7 @@ func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, header *types.
|
|||
// caller may optionally pass in a batch of parents (ascending order) to avoid
|
||||
// looking those up from the database. This is useful for concurrently verifying
|
||||
// a batch of new headers.
|
||||
func (c *Posv) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||
func (c *Posv) verifyHeader(chain consensus.ChainReader, state *state.StateDB, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||
if header.Number == nil {
|
||||
return errUnknownBlock
|
||||
}
|
||||
|
|
@ -357,14 +357,14 @@ func (c *Posv) verifyHeader(chain consensus.ChainReader, header *types.Header, p
|
|||
return err
|
||||
}
|
||||
// All basic checks passed, verify cascading fields
|
||||
return c.verifyCascadingFields(chain, header, parents, fullVerify)
|
||||
return c.verifyCascadingFields(chain, state, header, parents, fullVerify)
|
||||
}
|
||||
|
||||
// verifyCascadingFields verifies all the header fields that are not standalone,
|
||||
// rather depend on a batch of previous headers. The caller may optionally pass
|
||||
// in a batch of parents (ascending order) to avoid looking those up from the
|
||||
// database. This is useful for concurrently verifying a batch of new headers.
|
||||
func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||
func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, state *state.StateDB, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||
// The genesis block is the always valid dead-end
|
||||
number := header.Number.Uint64()
|
||||
if number == 0 {
|
||||
|
|
@ -390,8 +390,6 @@ func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types.
|
|||
}
|
||||
// If the block is a checkpoint block, verify the signer list
|
||||
if number%c.config.Epoch == 0 {
|
||||
database := state.NewDatabase(c.db)
|
||||
state, _ := state.New(parent.Hash(), database)
|
||||
penPenalties := []common.Address{}
|
||||
if c.HookPenalty != nil {
|
||||
penPenalties, err = c.HookPenalty(state, chain, number)
|
||||
|
|
@ -541,7 +539,7 @@ func (c *Posv) snapshot(chain consensus.ChainReader, number uint64, hash common.
|
|||
// If we're at block zero, make a snapshot
|
||||
if number == 0 {
|
||||
genesis := chain.GetHeaderByNumber(0)
|
||||
if err := c.VerifyHeader(chain, genesis, true); err != nil {
|
||||
if err := c.VerifyHeader(chain, nil, genesis, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
signers := make([]common.Address, (len(genesis.Extra)-extraVanity-extraSeal)/common.AddressLength)
|
||||
|
|
@ -731,7 +729,7 @@ func (c *Posv) GetValidator(creator common.Address, chain consensus.ChainReader,
|
|||
|
||||
// Prepare implements consensus.Engine, preparing all the consensus fields of the
|
||||
// header for running the transactions on top.
|
||||
func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error {
|
||||
func (c *Posv) Prepare(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error {
|
||||
// If the block isn't a checkpoint, cast a random vote (good enough for now)
|
||||
header.Coinbase = common.Address{}
|
||||
header.Nonce = types.BlockNonce{}
|
||||
|
|
@ -777,8 +775,6 @@ func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error
|
|||
header.Extra = header.Extra[:extraVanity]
|
||||
masternodes := snap.GetSigners()
|
||||
if number > 0 && number%c.config.Epoch == 0 {
|
||||
database := state.NewDatabase(c.db)
|
||||
state, _ := state.New(parent.Hash(), database)
|
||||
if c.HookPenalty != nil {
|
||||
penMasternodes, err := c.HookPenalty(state, chain, number)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -1069,7 +1069,11 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
|
|||
seals[i] = true
|
||||
bc.downloadingBlock.Add(block.Hash(), true)
|
||||
}
|
||||
abort, results := bc.engine.VerifyHeaders(bc, headers, seals)
|
||||
st, err := bc.State()
|
||||
if err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
abort, results := bc.engine.VerifyHeaders(bc, st, headers, seals)
|
||||
defer close(abort)
|
||||
|
||||
// Iterate over the blocks and insert when the verifier permits
|
||||
|
|
@ -1246,7 +1250,11 @@ func (bc *BlockChain) PrepareBlock(block *types.Block) (err error) {
|
|||
log.Debug("Stop prepare a block because inserting", "number", block.NumberU64(), "hash", block.Hash(), "validator", block.Header().Validator)
|
||||
return nil
|
||||
}
|
||||
err = bc.engine.VerifyHeader(bc, block.Header(), false)
|
||||
state, err := bc.State()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = bc.engine.VerifyHeader(bc, state, block.Header(), false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -1678,7 +1686,11 @@ Error: %v
|
|||
// because nonces can be verified sparsely, not needing to check each.
|
||||
func (bc *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
|
||||
start := time.Now()
|
||||
if i, err := bc.hc.ValidateHeaderChain(chain, checkFreq); err != nil {
|
||||
state, err := bc.State()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if i, err := bc.hc.ValidateHeaderChain(chain, state, checkFreq); err != nil {
|
||||
return i, err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/hashicorp/golang-lru"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -203,7 +204,7 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
|
|||
// header writes should be protected by the parent chain mutex individually.
|
||||
type WhCallback func(*types.Header) error
|
||||
|
||||
func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
|
||||
func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, state *state.StateDB, checkFreq int) (int, error) {
|
||||
// Do a sanity check that the provided chain is actually ordered and linked
|
||||
for i := 1; i < len(chain); i++ {
|
||||
if chain[i].Number.Uint64() != chain[i-1].Number.Uint64()+1 || chain[i].ParentHash != chain[i-1].Hash() {
|
||||
|
|
@ -227,7 +228,7 @@ func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int)
|
|||
}
|
||||
seals[len(seals)-1] = true // Last should always be verified to avoid junk
|
||||
|
||||
abort, results := hc.engine.VerifyHeaders(hc, chain, seals)
|
||||
abort, results := hc.engine.VerifyHeaders(hc, state, chain, seals)
|
||||
defer close(abort)
|
||||
|
||||
// Iterate over the headers and ensure they all check out
|
||||
|
|
|
|||
|
|
@ -387,7 +387,11 @@ func (api *PrivateDebugAPI) TraceBlockFromFile(ctx context.Context, file string,
|
|||
// per transaction, dependent on the requestd tracer.
|
||||
func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) {
|
||||
// Create the parent state database
|
||||
if err := api.eth.engine.VerifyHeader(api.eth.blockchain, block.Header(), true); err != nil {
|
||||
state, err := api.eth.blockchain.State()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = api.eth.engine.VerifyHeader(api.eth.blockchain, state, block.Header(), true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parent := api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
|
||||
|
|
|
|||
|
|
@ -393,29 +393,31 @@ func CreateConsensusEngine(ctx *node.ServiceContext, config *ethash.Config, chai
|
|||
if chainConfig.Posv != nil {
|
||||
return posv.New(chainConfig.Posv, db)
|
||||
}
|
||||
// Otherwise assume proof-of-work
|
||||
switch {
|
||||
case config.PowMode == ethash.ModeFake:
|
||||
log.Warn("Ethash used in fake mode")
|
||||
return ethash.NewFaker()
|
||||
case config.PowMode == ethash.ModeTest:
|
||||
log.Warn("Ethash used in test mode")
|
||||
return ethash.NewTester()
|
||||
case config.PowMode == ethash.ModeShared:
|
||||
log.Warn("Ethash used in shared mode")
|
||||
return ethash.NewShared()
|
||||
default:
|
||||
engine := ethash.New(ethash.Config{
|
||||
CacheDir: ctx.ResolvePath(config.CacheDir),
|
||||
CachesInMem: config.CachesInMem,
|
||||
CachesOnDisk: config.CachesOnDisk,
|
||||
DatasetDir: config.DatasetDir,
|
||||
DatasetsInMem: config.DatasetsInMem,
|
||||
DatasetsOnDisk: config.DatasetsOnDisk,
|
||||
})
|
||||
engine.SetThreads(-1) // Disable CPU mining
|
||||
return engine
|
||||
}
|
||||
// Otherwise, return nil
|
||||
return nil
|
||||
//// Otherwise assume proof-of-work
|
||||
//switch {
|
||||
//case config.PowMode == ethash.ModeFake:
|
||||
// log.Warn("Ethash used in fake mode")
|
||||
// return ethash.NewFaker()
|
||||
//case config.PowMode == ethash.ModeTest:
|
||||
// log.Warn("Ethash used in test mode")
|
||||
// return ethash.NewTester()
|
||||
//case config.PowMode == ethash.ModeShared:
|
||||
// log.Warn("Ethash used in shared mode")
|
||||
// return ethash.NewShared()
|
||||
//default:
|
||||
// engine := ethash.New(ethash.Config{
|
||||
// CacheDir: ctx.ResolvePath(config.CacheDir),
|
||||
// CachesInMem: config.CachesInMem,
|
||||
// CachesOnDisk: config.CachesOnDisk,
|
||||
// DatasetDir: config.DatasetDir,
|
||||
// DatasetsInMem: config.DatasetsInMem,
|
||||
// DatasetsOnDisk: config.DatasetsOnDisk,
|
||||
// })
|
||||
// engine.SetThreads(-1) // Disable CPU mining
|
||||
// return engine
|
||||
//}
|
||||
}
|
||||
|
||||
// APIs returns the collection of RPC services the ethereum package offers.
|
||||
|
|
|
|||
|
|
@ -165,7 +165,11 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne
|
|||
manager.downloader = downloader.New(mode, chaindb, manager.eventMux, blockchain, nil, manager.removePeer)
|
||||
|
||||
validator := func(header *types.Header) error {
|
||||
return engine.VerifyHeader(blockchain, header, true)
|
||||
state, err := blockchain.State()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return engine.VerifyHeader(blockchain, state, header, true)
|
||||
}
|
||||
heighter := func() uint64 {
|
||||
return blockchain.CurrentBlock().NumberU64()
|
||||
|
|
|
|||
|
|
@ -344,7 +344,11 @@ func (self *LightChain) postChainEvents(events []interface{}) {
|
|||
// chain events when necessary.
|
||||
func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
|
||||
start := time.Now()
|
||||
if i, err := self.hc.ValidateHeaderChain(chain, checkFreq); err != nil {
|
||||
state, err := self.State()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if i, err := self.hc.ValidateHeaderChain(chain, state, checkFreq); err != nil {
|
||||
return i, err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ func (self *worker) commitNewWork() {
|
|||
if atomic.LoadInt32(&self.mining) == 1 {
|
||||
header.Coinbase = self.coinbase
|
||||
}
|
||||
if err := self.engine.Prepare(self.chain, header); err != nil {
|
||||
if err := self.engine.Prepare(self.chain, self.current.state, header); err != nil {
|
||||
log.Error("Failed to prepare header for new block", "err", err)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue