core/state, core, miner: handle missing root error from state.New

This commit is contained in:
Gustav Simonsson
2015-10-06 16:35:55 +02:00
parent f466243417
commit 1b1f293082
23 changed files with 182 additions and 95 deletions

View File

@ -48,7 +48,7 @@ const (
maxQueued = 64 // max limit of queued txs per address
)
type stateFn func() *state.StateDB
type stateFn func() (*state.StateDB, error)
// TxPool contains all currently known transactions. Transactions
// enter the pool when they are received from the network or submitted
@ -80,7 +80,7 @@ func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func(
currentState: currentStateFn,
gasLimit: gasLimitFn,
minGasPrice: new(big.Int),
pendingState: state.ManageState(currentStateFn()),
pendingState: nil,
events: eventMux.Subscribe(ChainHeadEvent{}, GasPriceChanged{}, RemovedTransactionEvent{}),
}
go pool.eventLoop()
@ -109,7 +109,17 @@ func (pool *TxPool) eventLoop() {
}
func (pool *TxPool) resetState() {
pool.pendingState = state.ManageState(pool.currentState())
currentState, err := pool.currentState()
if err != nil {
glog.V(logger.Info).Infoln("failed to get current state: %v", err)
return
}
managedState := state.ManageState(currentState)
if err != nil {
glog.V(logger.Info).Infoln("failed to get managed state: %v", err)
return
}
pool.pendingState = managedState
// validate the pool of pending transactions, this will remove
// any transactions that have been included in the block or
@ -180,12 +190,16 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
// Make sure the account exist. Non existent accounts
// haven't got funds and well therefor never pass.
if !pool.currentState().HasAccount(from) {
currentState, err := pool.currentState()
if err != nil {
return err
}
if !currentState.HasAccount(from) {
return ErrNonExistentAccount
}
// Last but not least check for nonce errors
if pool.currentState().GetNonce(from) > tx.Nonce() {
if currentState.GetNonce(from) > tx.Nonce() {
return ErrNonce
}
@ -204,7 +218,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
// Transactor should have enough funds to cover the costs
// cost == V + GP * GL
if pool.currentState().GetBalance(from).Cmp(tx.Cost()) < 0 {
if currentState.GetBalance(from).Cmp(tx.Cost()) < 0 {
return ErrInsufficientFunds
}
@ -257,6 +271,11 @@ func (self *TxPool) queueTx(hash common.Hash, tx *types.Transaction) {
// addTx will add a transaction to the pending (processable queue) list of transactions
func (pool *TxPool) addTx(hash common.Hash, addr common.Address, tx *types.Transaction) {
// init delayed since tx pool could have been started before any state sync
if pool.pendingState == nil {
pool.resetState()
}
if _, ok := pool.pending[hash]; !ok {
pool.pending[hash] = tx
@ -382,14 +401,22 @@ func (pool *TxPool) RemoveTx(hash common.Hash) {
// checkQueue moves transactions that have become processable to main pool.
func (pool *TxPool) checkQueue() {
state := pool.pendingState
// init delayed since tx pool could have been started before any state sync
if pool.pendingState == nil {
pool.resetState()
}
var addq txQueue
for address, txs := range pool.queue {
// guessed nonce is the nonce currently kept by the tx pool (pending state)
guessedNonce := state.GetNonce(address)
guessedNonce := pool.pendingState.GetNonce(address)
// true nonce is the nonce known by the last state
trueNonce := pool.currentState().GetNonce(address)
currentState, err := pool.currentState()
if err != nil {
glog.Errorf("could not get current state: %v", err)
return
}
trueNonce := currentState.GetNonce(address)
addq := addq[:0]
for hash, tx := range txs {
if tx.Nonce() < trueNonce {
@ -434,7 +461,11 @@ func (pool *TxPool) checkQueue() {
// validatePool removes invalid and processed transactions from the main pool.
func (pool *TxPool) validatePool() {
state := pool.currentState()
state, err := pool.currentState()
if err != nil {
glog.V(logger.Info).Infoln("failed to get current state: %v", err)
return
}
for hash, tx := range pool.pending {
from, _ := tx.From() // err already checked
// perform light nonce validation