remove state at verifyHeader, prepare

This commit is contained in:
Tuna 2019-01-12 13:08:01 +07:00
parent eadb17b2bd
commit 337b7c64ee
8 changed files with 30 additions and 49 deletions

View file

@ -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, state *state.StateDB, header *types.Header, fullVerify bool) error
VerifyHeader(chain ChainReader, 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, state *state.StateDB, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error)
VerifyHeaders(chain ChainReader, 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, state *state.StateDB, header *types.Header) error
Prepare(chain ChainReader, header *types.Header) error
// Finalize runs any post-transaction state modifications (e.g. block rewards)
// and assembles the final block.

View file

@ -66,7 +66,7 @@ func (ethash *Ethash) Author(header *types.Header) (common.Address, error) {
// VerifyHeader checks whether a header conforms to the consensus rules of the
// stock Ethereum ethash engine.
func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, state *state.StateDB, header *types.Header, seal bool) error {
func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
// If we're running a full engine faking, accept any input as valid
if ethash.config.PowMode == ModeFullFake {
return nil
@ -81,13 +81,13 @@ func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, state *state.Sta
return consensus.ErrUnknownAncestor
}
// Sanity checks passed, do a proper verification
return ethash.verifyHeader(chain, state, header, parent, false, seal)
return ethash.verifyHeader(chain, header, parent, false, seal)
}
// 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.
func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, state *state.StateDB, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
// If we're running a full engine faking, accept any input as valid
if ethash.config.PowMode == ModeFullFake || len(headers) == 0 {
abort, results := make(chan struct{}), make(chan error, len(headers))
@ -113,7 +113,7 @@ func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, state *state.St
for i := 0; i < workers; i++ {
go func() {
for index := range inputs {
errors[index] = ethash.verifyHeaderWorker(chain, state, headers, seals, index)
errors[index] = ethash.verifyHeaderWorker(chain, headers, seals, index)
done <- index
}
}()
@ -149,7 +149,7 @@ func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, state *state.St
return abort, errorsOut
}
func (ethash *Ethash) verifyHeaderWorker(chain consensus.ChainReader, state *state.StateDB, headers []*types.Header, seals []bool, index int) error {
func (ethash *Ethash) verifyHeaderWorker(chain consensus.ChainReader, headers []*types.Header, seals []bool, index int) error {
var parent *types.Header
if index == 0 {
parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1)
@ -162,7 +162,7 @@ func (ethash *Ethash) verifyHeaderWorker(chain consensus.ChainReader, state *sta
if chain.GetHeader(headers[index].Hash(), headers[index].Number.Uint64()) != nil {
return nil // known block
}
return ethash.verifyHeader(chain, state, headers[index], parent, false, seals[index])
return ethash.verifyHeader(chain, headers[index], parent, false, seals[index])
}
// VerifyUncles verifies that the given block's uncles conform to the consensus
@ -210,7 +210,7 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo
if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() {
return errDanglingUncle
}
if err := ethash.verifyHeader(chain, nil, uncle, ancestors[uncle.ParentHash], true, true); err != nil {
if err := ethash.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, true); err != nil {
return err
}
}
@ -220,7 +220,7 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo
// verifyHeader checks whether a header conforms to the consensus rules of the
// stock Ethereum ethash engine.
// See YP section 4.3.4. "Block Header Validity"
func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, state *state.StateDB, header, parent *types.Header, uncle bool, seal bool) error {
func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error {
// Ensure that the header's extra-data section is of a reasonable size
if uint64(len(header.Extra)) > params.MaximumExtraDataSize {
return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize)
@ -502,7 +502,7 @@ func (ethash *Ethash) VerifySeal(chain consensus.ChainReader, header *types.Head
// Prepare implements consensus.Engine, initializing the difficulty field of a
// header to conform to the ethash protocol. The changes are done inline.
func (ethash *Ethash) Prepare(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error {
func (ethash *Ethash) Prepare(chain consensus.ChainReader, header *types.Header) error {
parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1)
if parent == nil {
return consensus.ErrUnknownAncestor

View file

@ -265,20 +265,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, state *state.StateDB, header *types.Header, fullVerify bool) error {
return c.verifyHeaderWithCache(chain, state, header, nil, fullVerify)
func (c *Posv) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error {
return c.verifyHeaderWithCache(chain, 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, state *state.StateDB, headers []*types.Header, fullVerifies []bool) (chan<- struct{}, <-chan error) {
func (c *Posv) VerifyHeaders(chain consensus.ChainReader, 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, state, header, headers[:i], fullVerifies[i])
err := c.verifyHeaderWithCache(chain, header, headers[:i], fullVerifies[i])
select {
case <-abort:
@ -290,12 +290,12 @@ func (c *Posv) VerifyHeaders(chain consensus.ChainReader, state *state.StateDB,
return abort, results
}
func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, state *state.StateDB, header *types.Header, parents []*types.Header, fullVerify bool) error {
func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
_, check := c.verifiedHeaders.Get(header.Hash())
if check {
return nil
}
err := c.verifyHeader(chain, state, header, parents, fullVerify)
err := c.verifyHeader(chain, header, parents, fullVerify)
if err == nil {
c.verifiedHeaders.Add(header.Hash(), true)
}
@ -306,7 +306,7 @@ func (c *Posv) verifyHeaderWithCache(chain consensus.ChainReader, state *state.S
// 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, state *state.StateDB, header *types.Header, parents []*types.Header, fullVerify bool) error {
func (c *Posv) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
if header.Number == nil {
return errUnknownBlock
}
@ -361,14 +361,14 @@ func (c *Posv) verifyHeader(chain consensus.ChainReader, state *state.StateDB, h
return err
}
// All basic checks passed, verify cascading fields
return c.verifyCascadingFields(chain, state, header, parents, fullVerify)
return c.verifyCascadingFields(chain, 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, state *state.StateDB, header *types.Header, parents []*types.Header, fullVerify bool) error {
func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, 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 {
@ -543,7 +543,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, nil, genesis, true); err != nil {
if err := c.VerifyHeader(chain, genesis, true); err != nil {
return nil, err
}
signers := make([]common.Address, (len(genesis.Extra)-extraVanity-extraSeal)/common.AddressLength)
@ -733,7 +733,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, state *state.StateDB, header *types.Header) error {
func (c *Posv) Prepare(chain consensus.ChainReader, 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{}

View file

@ -1075,11 +1075,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
seals[i] = true
bc.downloadingBlock.Add(block.Hash(), true)
}
st, err := bc.State()
if err != nil {
return 0, nil, nil, err
}
abort, results := bc.engine.VerifyHeaders(bc, st, headers, seals)
abort, results := bc.engine.VerifyHeaders(bc, headers, seals)
defer close(abort)
// Iterate over the blocks and insert when the verifier permits
@ -1256,11 +1252,7 @@ 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
}
state, err := bc.State()
if err != nil {
return err
}
err = bc.engine.VerifyHeader(bc, state, block.Header(), false)
err = bc.engine.VerifyHeader(bc, block.Header(), false)
if err != nil {
return err
}

View file

@ -228,7 +228,7 @@ func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, state *state.S
}
seals[len(seals)-1] = true // Last should always be verified to avoid junk
abort, results := hc.engine.VerifyHeaders(hc, state, chain, seals)
abort, results := hc.engine.VerifyHeaders(hc, chain, seals)
defer close(abort)
// Iterate over the headers and ensure they all check out

View file

@ -387,11 +387,7 @@ 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
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 {
if err := api.eth.engine.VerifyHeader(api.eth.blockchain, block.Header(), true); err != nil {
return nil, err
}
parent := api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)

View file

@ -165,11 +165,7 @@ 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 {
state, err := blockchain.State()
if err != nil {
return err
}
return engine.VerifyHeader(blockchain, state, header, true)
return engine.VerifyHeader(blockchain, header, true)
}
heighter := func() uint64 {
return blockchain.CurrentBlock().NumberU64()

View file

@ -552,11 +552,8 @@ func (self *worker) commitNewWork() {
if atomic.LoadInt32(&self.mining) == 1 {
header.Coinbase = self.coinbase
}
state := &state.StateDB{}
if self.current != nil {
state = self.current.state
}
if err := self.engine.Prepare(self.chain, state, header); err != nil {
if err := self.engine.Prepare(self.chain, header); err != nil {
log.Error("Failed to prepare header for new block", "err", err)
return
}