@ -17,6 +17,7 @@
package eth
import (
"context"
"errors"
"fmt"
"time"
@ -56,7 +57,7 @@ var noopReleaser = tracers.StateReleaseFunc(func() {})
// - preferDisk: this arg can be used by the caller to signal that even though the 'base' is
// provided, it would be preferable to start from a fresh state, if we have it
// on disk.
func ( eth * Ethereum ) StateAtBlock ( block * types . Block , reexec uint64 , base * state . StateDB , readOnly bool , preferDisk bool ) ( statedb * state . StateDB , release tracers . StateReleaseFunc , err error ) {
func ( eth * Ethereum ) StateAtBlock ( ctx context . Context , block * types . Block , reexec uint64 , base * state . StateDB , readOnly bool , preferDisk bool ) ( statedb * state . StateDB , release tracers . StateReleaseFunc , err error ) {
var (
current * types . Block
database state . Database
@ -111,6 +112,9 @@ func (eth *Ethereum) StateAtBlock(block *types.Block, reexec uint64, base *state
}
// Database does not have the state for the given block, try to regenerate
for i := uint64 ( 0 ) ; i < reexec ; i ++ {
if err := ctx . Err ( ) ; err != nil {
return nil , nil , err
}
if current . NumberU64 ( ) == 0 {
return nil , nil , errors . New ( "genesis state is missing" )
}
@ -142,6 +146,9 @@ func (eth *Ethereum) StateAtBlock(block *types.Block, reexec uint64, base *state
parent common . Hash
)
for current . NumberU64 ( ) < origin {
if err := ctx . Err ( ) ; err != nil {
return nil , nil , err
}
// Print progress logs if long enough time elapsed
if time . Since ( logged ) > 8 * time . Second && report {
log . Info ( "Regenerating historical state" , "block" , current . NumberU64 ( ) + 1 , "target" , origin , "remaining" , origin - current . NumberU64 ( ) - 1 , "elapsed" , time . Since ( start ) )
@ -182,7 +189,7 @@ func (eth *Ethereum) StateAtBlock(block *types.Block, reexec uint64, base *state
}
// stateAtTransaction returns the execution environment of a certain transaction.
func ( eth * Ethereum ) stateAtTransaction ( block * types . Block , txIndex int , reexec uint64 ) ( core . Message , vm . BlockContext , * state . StateDB , tracers . StateReleaseFunc , error ) {
func ( eth * Ethereum ) stateAtTransaction ( ctx context . Context , block * types . Block , txIndex int , reexec uint64 ) ( core . Message , vm . BlockContext , * state . StateDB , tracers . StateReleaseFunc , error ) {
// Short circuit if it's genesis block.
if block . NumberU64 ( ) == 0 {
return nil , vm . BlockContext { } , nil , nil , errors . New ( "no transaction in genesis" )
@ -194,7 +201,7 @@ func (eth *Ethereum) stateAtTransaction(block *types.Block, txIndex int, reexec
}
// Lookup the statedb of parent block from the live database,
// otherwise regenerate it on the flight.
statedb , release , err := eth . StateAtBlock ( parent , reexec , nil , true , false )
statedb , release , err := eth . StateAtBlock ( ctx , parent , reexec , nil , true , false )
if err != nil {
return nil , vm . BlockContext { } , nil , nil , err
}