core/state: access trie through Database interface, track errors (#14589)
With this commit, core/state's access to the underlying key/value database is mediated through an interface. Database errors are tracked in StateDB and returned by CommitTo or the new Error method. Motivation for this change: We can remove the light client's duplicated copy of core/state. The light client now supports node iteration, so tracing and storage enumeration can work with the light client (not implemented in this commit).
This commit is contained in:
@ -24,6 +24,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
@ -100,17 +101,18 @@ func NewTxPool(config *params.ChainConfig, eventMux *event.TypeMux, chain *Light
|
||||
}
|
||||
|
||||
// currentState returns the light state of the current head header
|
||||
func (pool *TxPool) currentState() *LightState {
|
||||
return NewLightState(StateTrieID(pool.chain.CurrentHeader()), pool.odr)
|
||||
func (pool *TxPool) currentState(ctx context.Context) *state.StateDB {
|
||||
return NewState(ctx, pool.chain.CurrentHeader(), pool.odr)
|
||||
}
|
||||
|
||||
// GetNonce returns the "pending" nonce of a given address. It always queries
|
||||
// the nonce belonging to the latest header too in order to detect if another
|
||||
// client using the same key sent a transaction.
|
||||
func (pool *TxPool) GetNonce(ctx context.Context, addr common.Address) (uint64, error) {
|
||||
nonce, err := pool.currentState().GetNonce(ctx, addr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
state := pool.currentState(ctx)
|
||||
nonce := state.GetNonce(addr)
|
||||
if state.Error() != nil {
|
||||
return 0, state.Error()
|
||||
}
|
||||
sn, ok := pool.nonce[addr]
|
||||
if ok && sn > nonce {
|
||||
@ -357,13 +359,9 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
|
||||
return core.ErrInvalidSender
|
||||
}
|
||||
// Last but not least check for nonce errors
|
||||
currentState := pool.currentState()
|
||||
if n, err := currentState.GetNonce(ctx, from); err == nil {
|
||||
if n > tx.Nonce() {
|
||||
return core.ErrNonceTooLow
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
currentState := pool.currentState(ctx)
|
||||
if n := currentState.GetNonce(from); n > tx.Nonce() {
|
||||
return core.ErrNonceTooLow
|
||||
}
|
||||
|
||||
// Check the transaction doesn't exceed the current
|
||||
@ -382,12 +380,8 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
|
||||
|
||||
// Transactor should have enough funds to cover the costs
|
||||
// cost == V + GP * GL
|
||||
if b, err := currentState.GetBalance(ctx, from); err == nil {
|
||||
if b.Cmp(tx.Cost()) < 0 {
|
||||
return core.ErrInsufficientFunds
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
if b := currentState.GetBalance(from); b.Cmp(tx.Cost()) < 0 {
|
||||
return core.ErrInsufficientFunds
|
||||
}
|
||||
|
||||
// Should supply enough intrinsic gas
|
||||
@ -395,7 +389,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
|
||||
return core.ErrIntrinsicGas
|
||||
}
|
||||
|
||||
return nil
|
||||
return currentState.Error()
|
||||
}
|
||||
|
||||
// add validates a new transaction and sets its state pending if processable.
|
||||
|
Reference in New Issue
Block a user