This commit is contained in:
Devon Bear 2023-10-07 22:35:02 -04:00
parent dc34fe8291
commit 25ba0940d7
94 changed files with 794 additions and 406 deletions

View file

@ -65,7 +65,7 @@ type SimulatedBackend struct {
mu sync.Mutex mu sync.Mutex
pendingBlock *types.Block // Currently pending block that will be imported on request pendingBlock *types.Block // Currently pending block that will be imported on request
pendingState *state.StateDB // Currently pending state that will be the active on request pendingState state.StateDBI // Currently pending state that will be the active on request
pendingReceipts types.Receipts // Currently receipts for the pending block pendingReceipts types.Receipts // Currently receipts for the pending block
events *filters.EventSystem // for filtering log events live events *filters.EventSystem // for filtering log events live
@ -179,7 +179,7 @@ func (b *SimulatedBackend) Fork(ctx context.Context, parent common.Hash) error {
} }
// stateByBlockNumber retrieves a state by a given blocknumber. // stateByBlockNumber retrieves a state by a given blocknumber.
func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber *big.Int) (*state.StateDB, error) { func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber *big.Int) (state.StateDBI, error) {
if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number) == 0 { if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number) == 0 {
return b.blockchain.State() return b.blockchain.State()
} }
@ -580,7 +580,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
} }
} }
// Reject the transaction as invalid if it still fails at the highest allowance // Reject the transaction as invalid if it still fails at the highest allowance
if hi == cap { if hi >= cap {
failed, result, err := executable(hi) failed, result, err := executable(hi)
if err != nil { if err != nil {
return 0, err return 0, err
@ -601,7 +601,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
// callContract implements common code between normal and pending contract calls. // callContract implements common code between normal and pending contract calls.
// state is modified during execution, make sure to copy it if necessary. // state is modified during execution, make sure to copy it if necessary.
func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, header *types.Header, stateDB *state.StateDB) (*core.ExecutionResult, error) { func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, header *types.Header, stateDB state.StateDBI) (*core.ExecutionResult, error) {
// Gas prices post 1559 need to be initialized // Gas prices post 1559 need to be initialized
if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) { if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")

View file

@ -42,7 +42,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"

View file

@ -117,7 +117,7 @@ type rejectedTx struct {
// Apply applies a set of transactions to a pre-state // Apply applies a set of transactions to a pre-state
func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
txs types.Transactions, miningReward int64, txs types.Transactions, miningReward int64,
getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error)) (*state.StateDB, *ExecutionResult, error) { getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error)) (state.StateDBI, *ExecutionResult, error) {
// Capture errors for BLOCKHASH operation, if we haven't been supplied the // Capture errors for BLOCKHASH operation, if we haven't been supplied the
// required blockhashes // required blockhashes
var hashError error var hashError error
@ -335,7 +335,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
return statedb, execRs, nil return statedb, execRs, nil
} }
func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB { func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) state.StateDBI {
sdb := state.NewDatabaseWithConfig(db, &trie.Config{Preimages: true}) sdb := state.NewDatabaseWithConfig(db, &trie.Config{Preimages: true})
statedb, _ := state.New(types.EmptyRootHash, sdb, nil) statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
for addr, a := range accounts { for addr, a := range accounts {

View file

@ -116,14 +116,15 @@ func runCmd(ctx *cli.Context) error {
} }
var ( var (
tracer vm.EVMLogger tracer vm.EVMLogger
debugLogger *logger.StructLogger debugLogger *logger.StructLogger
statedb *state.StateDB statedb state.StateDBI
chainConfig *params.ChainConfig chainConfig *params.ChainConfig
sender = common.BytesToAddress([]byte("sender")) sender = common.BytesToAddress([]byte("sender"))
receiver = common.BytesToAddress([]byte("receiver")) receiver = common.BytesToAddress([]byte("receiver"))
preimages = ctx.Bool(DumpFlag.Name) genesisConfig *core.Genesis
blobHashes []common.Hash // TODO (MariusVanDerWijden) implement blob hashes in state tests preimages = ctx.Bool(DumpFlag.Name)
blobHashes []common.Hash // TODO (MariusVanDerWijden) implement blob hashes in state tests
) )
if ctx.Bool(MachineFlag.Name) { if ctx.Bool(MachineFlag.Name) {
tracer = logger.NewJSONLogger(logconfig, os.Stdout) tracer = logger.NewJSONLogger(logconfig, os.Stdout)

View file

@ -100,7 +100,7 @@ func runStateTest(fname string, cfg vm.Config, jsonOut, dump bool) error {
for _, st := range test.Subtests() { for _, st := range test.Subtests() {
// Run the test and aggregate the result // Run the test and aggregate the result
result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true} result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true}
test.Run(st, cfg, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) { test.Run(st, cfg, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state state.StateDBI) {
if state != nil { if state != nil {
root := state.IntermediateRoot(false) root := state.IntermediateRoot(false)
result.Root = &root result.Root = &root

View file

@ -35,7 +35,7 @@ import (
"github.com/ethereum/go-ethereum/eth/catalyst" "github.com/ethereum/go-ethereum/eth/catalyst"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/internal/version" "github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"

View file

@ -32,9 +32,9 @@ import (
"github.com/ethereum/go-ethereum/console/prompt" "github.com/ethereum/go-ethereum/console/prompt"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"

View file

@ -54,11 +54,11 @@ import (
"github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb/remotedb" "github.com/ethereum/go-ethereum/ethdb/remotedb"
"github.com/ethereum/go-ethereum/ethstats" "github.com/ethereum/go-ethereum/ethstats"
"github.com/ethereum/go-ethereum/graphql" "github.com/ethereum/go-ethereum/graphql"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/les" "github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
@ -1962,8 +1962,12 @@ func RegisterGraphQLService(stack *node.Node, backend ethapi.Backend, filterSyst
} }
} }
type NetworkingStack interface {
RegisterAPIs([]rpc.API)
}
// RegisterFilterAPI adds the eth log filtering RPC API to the node. // RegisterFilterAPI adds the eth log filtering RPC API to the node.
func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconfig.Config) *filters.FilterSystem { func RegisterFilterAPI(stack NetworkingStack, backend ethapi.Backend, ethcfg *ethconfig.Config) *filters.FilterSystem {
isLightClient := ethcfg.SyncMode == downloader.LightSync isLightClient := ethcfg.SyncMode == downloader.LightSync
filterSystem := filters.NewFilterSystem(backend, filters.Config{ filterSystem := filters.NewFilterSystem(backend, filters.Config{
LogCacheSize: ethcfg.FilterLogCacheSize, LogCacheSize: ethcfg.FilterLogCacheSize,

View file

@ -347,7 +347,9 @@ func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.H
} }
// Finalize implements consensus.Engine and processes withdrawals on top. // Finalize implements consensus.Engine and processes withdrawals on top.
func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) {
// Finalize is different with Prepare, it can be used in both block generation
// and verification. So determine the consensus rules by header type.
if !beacon.IsPoSHeader(header) { if !beacon.IsPoSHeader(header) {
beacon.ethone.Finalize(chain, header, state, txs, uncles, nil) beacon.ethone.Finalize(chain, header, state, txs, uncles, nil)
return return
@ -364,7 +366,9 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
// FinalizeAndAssemble implements consensus.Engine, setting the final state and // FinalizeAndAssemble implements consensus.Engine, setting the final state and
// assembling the block. // assembling the block.
func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) {
// FinalizeAndAssemble is different with Prepare, it can be used in both block
// generation and verification. So determine the consensus rules by header type.
if !beacon.IsPoSHeader(header) { if !beacon.IsPoSHeader(header) {
return beacon.ethone.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts, nil) return beacon.ethone.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts, nil)
} }

View file

@ -567,13 +567,15 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
// Finalize implements consensus.Engine. There is no post-transaction // Finalize implements consensus.Engine. There is no post-transaction
// consensus rules in clique, do nothing here. // consensus rules in clique, do nothing here.
func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) {
// No block rewards in PoA, so the state remains as is // No block rewards in PoA, so the state remains as is
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
header.UncleHash = types.CalcUncleHash(nil)
} }
// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
// nor block rewards given, and returns the final block. // nor block rewards given, and returns the final block.
func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) {
if len(withdrawals) > 0 { if len(withdrawals) > 0 {
return nil, errors.New("clique does not support withdrawals") return nil, errors.New("clique does not support withdrawals")
} }

View file

@ -88,7 +88,7 @@ type Engine interface {
// //
// Note: The state database might be updated to reflect any consensus rules // Note: The state database might be updated to reflect any consensus rules
// that happen at finalization (e.g. block rewards). // that happen at finalization (e.g. block rewards).
Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, Finalize(chain ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction,
uncles []*types.Header, withdrawals []*types.Withdrawal) uncles []*types.Header, withdrawals []*types.Withdrawal)
// FinalizeAndAssemble runs any post-transaction state modifications (e.g. block // FinalizeAndAssemble runs any post-transaction state modifications (e.g. block
@ -96,7 +96,7 @@ type Engine interface {
// //
// Note: The block header and state database might be updated to reflect any // Note: The block header and state database might be updated to reflect any
// consensus rules that happen at finalization (e.g. block rewards). // consensus rules that happen at finalization (e.g. block rewards).
FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction,
uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error)
// Seal generates a new sealing request for the given input block and pushes // Seal generates a new sealing request for the given input block and pushes

View file

@ -487,14 +487,14 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H
} }
// Finalize implements consensus.Engine, accumulating the block and uncle rewards. // Finalize implements consensus.Engine, accumulating the block and uncle rewards.
func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) {
// Accumulate any block and uncle rewards // Accumulate any block and uncle rewards
accumulateRewards(chain.Config(), state, header, uncles) accumulateRewards(chain.Config(), state, header, uncles)
} }
// FinalizeAndAssemble implements consensus.Engine, accumulating the block and // FinalizeAndAssemble implements consensus.Engine, accumulating the block and
// uncle rewards, setting the final state and assembling the block. // uncle rewards, setting the final state and assembling the block.
func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) {
if len(withdrawals) > 0 { if len(withdrawals) > 0 {
return nil, errors.New("ethash does not support withdrawals") return nil, errors.New("ethash does not support withdrawals")
} }
@ -547,7 +547,7 @@ var (
// AccumulateRewards credits the coinbase of the given block with the mining // AccumulateRewards credits the coinbase of the given block with the mining
// reward. The total reward consists of the static block reward and rewards for // reward. The total reward consists of the static block reward and rewards for
// included uncles. The coinbase of each uncle block is also rewarded. // included uncles. The coinbase of each uncle block is also rewarded.
func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) { func accumulateRewards(config *params.ChainConfig, state state.StateDBI, header *types.Header, uncles []*types.Header) {
// Select the correct block reward based on chain progression // Select the correct block reward based on chain progression
blockReward := FrontierBlockReward blockReward := FrontierBlockReward
if config.IsByzantium(header.Number) { if config.IsByzantium(header.Number) {

View file

@ -72,7 +72,7 @@ func VerifyDAOHeaderExtraData(config *params.ChainConfig, header *types.Header)
// ApplyDAOHardFork modifies the state database according to the DAO hard-fork // ApplyDAOHardFork modifies the state database according to the DAO hard-fork
// rules, transferring all balances of a set of DAO accounts to a single refund // rules, transferring all balances of a set of DAO accounts to a single refund
// contract. // contract.
func ApplyDAOHardFork(statedb *state.StateDB) { func ApplyDAOHardFork(statedb state.StateDBI) {
// Retrieve the contract to refund balances into // Retrieve the contract to refund balances into
if !statedb.Exist(params.DAORefundContract) { if !statedb.Exist(params.DAORefundContract) {
statedb.CreateAccount(params.DAORefundContract) statedb.CreateAccount(params.DAORefundContract)

View file

@ -121,7 +121,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
// ValidateState validates the various changes that happen after a state transition, // ValidateState validates the various changes that happen after a state transition,
// such as amount of used gas, the receipt roots and the state root itself. // such as amount of used gas, the receipt roots and the state root itself.
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error { func (v *BlockValidator) ValidateState(block *types.Block, statedb state.StateDBI, receipts types.Receipts, usedGas uint64) error {
header := block.Header() header := block.Header()
if block.GasUsed() != usedGas { if block.GasUsed() != usedGas {
return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas) return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)

View file

@ -1385,7 +1385,7 @@ func (bc *BlockChain) writeKnownBlock(block *types.Block) error {
// writeBlockWithState writes block, metadata and corresponding state data to the // writeBlockWithState writes block, metadata and corresponding state data to the
// database. // database.
func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, state *state.StateDB) error { func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, state state.StateDBI) error {
// Calculate the total difficulty of the block // Calculate the total difficulty of the block
ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1) ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1)
if ptd == nil { if ptd == nil {
@ -1473,7 +1473,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
// WriteBlockAndSetHead writes the given block and all associated state to the database, // WriteBlockAndSetHead writes the given block and all associated state to the database,
// and applies the block as the new chain head. // and applies the block as the new chain head.
func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) { func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state state.StateDBI, emitHeadEvent bool) (status WriteStatus, err error) {
if !bc.chainmu.TryLock() { if !bc.chainmu.TryLock() {
return NonStatTy, errChainStopped return NonStatTy, errChainStopped
} }
@ -1484,7 +1484,7 @@ func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead. // writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
// This function expects the chain mutex to be held. // This function expects the chain mutex to be held.
func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) { func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state state.StateDBI, emitHeadEvent bool) (status WriteStatus, err error) {
if err := bc.writeBlockWithState(block, receipts, state); err != nil { if err := bc.writeBlockWithState(block, receipts, state); err != nil {
return NonStatTy, err return NonStatTy, err
} }
@ -1710,7 +1710,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
return it.index, err return it.index, err
} }
// No validation errors for the first block (or chain prefix skipped) // No validation errors for the first block (or chain prefix skipped)
var activeState *state.StateDB var activeState state.StateDBI
defer func() { defer func() {
// The chain importer is starting and stopping trie prefetchers. If a bad // The chain importer is starting and stopping trie prefetchers. If a bad
// block or other error is hit however, an early return may not properly // block or other error is hit however, an early return may not properly
@ -1794,7 +1794,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
if followup, err := it.peek(); followup != nil && err == nil { if followup, err := it.peek(); followup != nil && err == nil {
throwaway, _ := state.New(parent.Root, bc.stateCache, bc.snaps) throwaway, _ := state.New(parent.Root, bc.stateCache, bc.snaps)
go func(start time.Time, followup *types.Block, throwaway *state.StateDB) { go func(start time.Time, followup *types.Block, throwaway state.StateDBI) {
bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt) bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt)
blockPrefetchExecuteTimer.Update(time.Since(start)) blockPrefetchExecuteTimer.Update(time.Since(start))

View file

@ -320,15 +320,20 @@ func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) ([]byte, error) {
} }
// State returns a new mutable state based on the current HEAD block. // State returns a new mutable state based on the current HEAD block.
func (bc *BlockChain) State() (*state.StateDB, error) { func (bc *BlockChain) State() (state.StateDBI, error) {
return bc.StateAt(bc.CurrentBlock().Root) return bc.StateAt(bc.CurrentBlock().Root)
} }
// StateAt returns a new mutable state based on a particular point in time. // StateAt returns a new mutable state based on a particular point in time.
func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) { func (bc *BlockChain) StateAt(root common.Hash) (state.StateDBI, error) {
return state.New(root, bc.stateCache, bc.snaps) return state.New(root, bc.stateCache, bc.snaps)
} }
// StateAtBlockNumber returns a new mutable state based on a particular block number.
func (bc *BlockChain) StateAtBlockNumber(number uint64) (state.StateDBI, error) {
return bc.StateAt(bc.GetHeaderByNumber(number).Root)
}
// Config retrieves the chain's fork configuration. // Config retrieves the chain's fork configuration.
func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig } func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig }

View file

@ -41,7 +41,7 @@ type BlockGen struct {
parent *types.Block parent *types.Block
chain []*types.Block chain []*types.Block
header *types.Header header *types.Header
statedb *state.StateDB statedb state.StateDBI
gasPool *GasPool gasPool *GasPool
txs []*types.Transaction txs []*types.Transaction
@ -289,7 +289,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
} }
blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n) blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n)
chainreader := &fakeChainReader{config: config} chainreader := &fakeChainReader{config: config}
genblock := func(i int, parent *types.Block, triedb *trie.Database, statedb *state.StateDB) (*types.Block, types.Receipts) { genblock := func(i int, parent *types.Block, triedb *trie.Database, statedb state.StateDBI) (*types.Block, types.Receipts) {
b := &BlockGen{i: i, chain: blocks, parent: parent, statedb: statedb, config: config, engine: engine} b := &BlockGen{i: i, chain: blocks, parent: parent, statedb: statedb, config: config, engine: engine}
b.header = makeHeader(chainreader, parent, statedb, b.engine) b.header = makeHeader(chainreader, parent, statedb, b.engine)
@ -371,7 +371,7 @@ func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int,
return db, blocks, receipts return db, blocks, receipts
} }
func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.StateDB, engine consensus.Engine) *types.Header { func makeHeader(chain consensus.ChainReader, parent *types.Block, state state.StateDBI, engine consensus.Engine) *types.Header {
var time uint64 var time uint64
if parent.Time() == 0 { if parent.Time() == 0 {
time = 10 time = 10

View file

@ -20,20 +20,20 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
type accessList struct { type AccessList struct {
addresses map[common.Address]int addresses map[common.Address]int
slots []map[common.Hash]struct{} slots []map[common.Hash]struct{}
} }
// ContainsAddress returns true if the address is in the access list. // ContainsAddress returns true if the address is in the access list.
func (al *accessList) ContainsAddress(address common.Address) bool { func (al *AccessList) ContainsAddress(address common.Address) bool {
_, ok := al.addresses[address] _, ok := al.addresses[address]
return ok return ok
} }
// Contains checks if a slot within an account is present in the access list, returning // Contains checks if a slot within an account is present in the access list, returning
// separate flags for the presence of the account and the slot respectively. // separate flags for the presence of the account and the slot respectively.
func (al *accessList) Contains(address common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) { func (al *AccessList) Contains(address common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) {
idx, ok := al.addresses[address] idx, ok := al.addresses[address]
if !ok { if !ok {
// no such address (and hence zero slots) // no such address (and hence zero slots)
@ -47,16 +47,16 @@ func (al *accessList) Contains(address common.Address, slot common.Hash) (addres
return true, slotPresent return true, slotPresent
} }
// newAccessList creates a new accessList. // NewAccessList creates a new AccessList.
func newAccessList() *accessList { func NewAccessList() *AccessList {
return &accessList{ return &AccessList{
addresses: make(map[common.Address]int), addresses: make(map[common.Address]int),
} }
} }
// Copy creates an independent copy of an accessList. // Copy creates an independent copy of an AccessList.
func (a *accessList) Copy() *accessList { func (a *AccessList) Copy() *AccessList {
cp := newAccessList() cp := NewAccessList()
for k, v := range a.addresses { for k, v := range a.addresses {
cp.addresses[k] = v cp.addresses[k] = v
} }
@ -73,7 +73,7 @@ func (a *accessList) Copy() *accessList {
// AddAddress adds an address to the access list, and returns 'true' if the operation // AddAddress adds an address to the access list, and returns 'true' if the operation
// caused a change (addr was not previously in the list). // caused a change (addr was not previously in the list).
func (al *accessList) AddAddress(address common.Address) bool { func (al *AccessList) AddAddress(address common.Address) bool {
if _, present := al.addresses[address]; present { if _, present := al.addresses[address]; present {
return false return false
} }
@ -86,7 +86,7 @@ func (al *accessList) AddAddress(address common.Address) bool {
// - address added // - address added
// - slot added // - slot added
// For any 'true' value returned, a corresponding journal entry must be made. // For any 'true' value returned, a corresponding journal entry must be made.
func (al *accessList) AddSlot(address common.Address, slot common.Hash) (addrChange bool, slotChange bool) { func (al *AccessList) AddSlot(address common.Address, slot common.Hash) (addrChange bool, slotChange bool) {
idx, addrPresent := al.addresses[address] idx, addrPresent := al.addresses[address]
if !addrPresent || idx == -1 { if !addrPresent || idx == -1 {
// Address not present, or addr present but no slots there // Address not present, or addr present but no slots there
@ -110,7 +110,7 @@ func (al *accessList) AddSlot(address common.Address, slot common.Hash) (addrCha
// This operation needs to be performed in the same order as the addition happened. // This operation needs to be performed in the same order as the addition happened.
// This method is meant to be used by the journal, which maintains ordering of // This method is meant to be used by the journal, which maintains ordering of
// operations. // operations.
func (al *accessList) DeleteSlot(address common.Address, slot common.Hash) { func (al *AccessList) DeleteSlot(address common.Address, slot common.Hash) {
idx, addrOk := al.addresses[address] idx, addrOk := al.addresses[address]
// There are two ways this can fail // There are two ways this can fail
if !addrOk { if !addrOk {
@ -131,6 +131,6 @@ func (al *accessList) DeleteSlot(address common.Address, slot common.Hash) {
// needs to be performed in the same order as the addition happened. // needs to be performed in the same order as the addition happened.
// This method is meant to be used by the journal, which maintains ordering of // This method is meant to be used by the journal, which maintains ordering of
// operations. // operations.
func (al *accessList) DeleteAddress(address common.Address) { func (al *AccessList) DeleteAddress(address common.Address) {
delete(al.addresses, address) delete(al.addresses, address)
} }

107
core/state/interface.go Normal file
View file

@ -0,0 +1,107 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package state provides a caching layer atop the Ethereum state trie.
package state
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)
// StateDBI is an EVM database for full state querying.
type StateDBI interface {
CreateAccount(common.Address)
SubBalance(common.Address, *big.Int)
AddBalance(common.Address, *big.Int)
GetBalance(common.Address) *big.Int
GetNonce(common.Address) uint64
SetNonce(common.Address, uint64)
GetCodeHash(common.Address) common.Hash
GetCode(common.Address) []byte
SetCode(common.Address, []byte)
GetCodeSize(common.Address) int
AddRefund(uint64)
SubRefund(uint64)
GetRefund() uint64
GetCommittedState(common.Address, common.Hash) common.Hash
GetState(common.Address, common.Hash) common.Hash
SetState(common.Address, common.Hash, common.Hash)
GetTransientState(addr common.Address, key common.Hash) common.Hash
SetTransientState(addr common.Address, key, value common.Hash)
SelfDestruct(common.Address)
HasSelfDestructed(common.Address) bool
Selfdestruct6780(common.Address)
// Exist reports whether the given account exists in state.
// Notably this should also return true for self-destructed accounts.
Exist(common.Address) bool
// Empty returns whether the given account is empty. Empty
// is defined according to EIP161 (balance = nonce = code = 0).
Empty(common.Address) bool
AddressInAccessList(addr common.Address) bool
SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool)
// AddAddressToAccessList adds the given address to the access list. This operation is safe to perform
// even if the feature/fork is not active yet
AddAddressToAccessList(addr common.Address)
// AddSlotToAccessList adds the given (address,slot) to the access list. This operation is safe to perform
// even if the feature/fork is not active yet
AddSlotToAccessList(addr common.Address, slot common.Hash)
Prepare(rules params.Rules, sender, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList)
RevertToSnapshot(int)
Snapshot() int
AddLog(*types.Log)
AddPreimage(common.Hash, []byte)
Logs() []*types.Log
GetLogs(hash common.Hash, blockNumber uint64, blockHash common.Hash) []*types.Log
TxIndex() int
Preimages() map[common.Hash][]byte
GetOrNewStateObject(addr common.Address) *StateObject
DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []byte)
Dump(opts *DumpConfig) []byte
RawDump(opts *DumpConfig) Dump
IteratorDump(opts *DumpConfig) IteratorDump
Database() Database
Error() error
SetBalance(addr common.Address, amount *big.Int)
SetStorage(addr common.Address, storage map[common.Hash]common.Hash)
GetStorageRoot(addr common.Address) common.Hash
Finalise(deleteEmptyObjects bool)
Commit(uint64, bool) (common.Hash, error)
Copy() StateDBI
SetTxContext(thash common.Hash, ti int)
StopPrefetcher()
StartPrefetcher(namespace string)
IntermediateRoot(deleteEmptyObjects bool) common.Hash
GetPrecompileManager() any
}

View file

@ -91,7 +91,7 @@ type (
} }
resetObjectChange struct { resetObjectChange struct {
account *common.Address account *common.Address
prev *stateObject prev *StateObject
prevdestruct bool prevdestruct bool
prevAccount []byte prevAccount []byte
prevStorage map[common.Hash][]byte prevStorage map[common.Hash][]byte

View file

@ -54,13 +54,13 @@ func (s Storage) Copy() Storage {
return cpy return cpy
} }
// stateObject represents an Ethereum account which is being modified. // StateObject represents an Ethereum account which is being modified.
// //
// The usage pattern is as follows: // The usage pattern is as follows:
// - First you need to obtain a state object. // - First you need to obtain a state object.
// - Account values as well as storages can be accessed and modified through the object. // - Account values as well as storages can be accessed and modified through the object.
// - Finally, call commit to return the changes of storage trie and update account data. // - Finally, call commit to return the changes of storage trie and update account data.
type stateObject struct { type StateObject struct {
db *StateDB db *StateDB
address common.Address // address of ethereum account address common.Address // address of ethereum account
addrHash common.Hash // hash of ethereum address of the account addrHash common.Hash // hash of ethereum address of the account
@ -92,17 +92,17 @@ type stateObject struct {
} }
// empty returns whether the account is considered empty. // empty returns whether the account is considered empty.
func (s *stateObject) empty() bool { func (s *StateObject) empty() bool {
return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, types.EmptyCodeHash.Bytes()) return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, types.EmptyCodeHash.Bytes())
} }
// newObject creates a state object. // newObject creates a state object.
func newObject(db *StateDB, address common.Address, acct *types.StateAccount) *stateObject { func newObject(db *StateDB, address common.Address, acct *types.StateAccount) *StateObject {
origin := acct origin := acct
if acct == nil { if acct == nil {
acct = types.NewEmptyStateAccount() acct = types.NewEmptyStateAccount()
} }
return &stateObject{ return &StateObject{
db: db, db: db,
address: address, address: address,
addrHash: crypto.Keccak256Hash(address[:]), addrHash: crypto.Keccak256Hash(address[:]),
@ -115,15 +115,15 @@ func newObject(db *StateDB, address common.Address, acct *types.StateAccount) *s
} }
// EncodeRLP implements rlp.Encoder. // EncodeRLP implements rlp.Encoder.
func (s *stateObject) EncodeRLP(w io.Writer) error { func (s *StateObject) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, &s.data) return rlp.Encode(w, &s.data)
} }
func (s *stateObject) markSelfdestructed() { func (s *StateObject) markSelfdestructed() {
s.selfDestructed = true s.selfDestructed = true
} }
func (s *stateObject) touch() { func (s *StateObject) touch() {
s.db.journal.append(touchChange{ s.db.journal.append(touchChange{
account: &s.address, account: &s.address,
}) })
@ -137,7 +137,7 @@ func (s *stateObject) touch() {
// getTrie returns the associated storage trie. The trie will be opened // getTrie returns the associated storage trie. The trie will be opened
// if it's not loaded previously. An error will be returned if trie can't // if it's not loaded previously. An error will be returned if trie can't
// be loaded. // be loaded.
func (s *stateObject) getTrie() (Trie, error) { func (s *StateObject) getTrie() (Trie, error) {
if s.trie == nil { if s.trie == nil {
// Try fetching from prefetcher first // Try fetching from prefetcher first
if s.data.Root != types.EmptyRootHash && s.db.prefetcher != nil { if s.data.Root != types.EmptyRootHash && s.db.prefetcher != nil {
@ -156,7 +156,7 @@ func (s *stateObject) getTrie() (Trie, error) {
} }
// GetState retrieves a value from the account storage trie. // GetState retrieves a value from the account storage trie.
func (s *stateObject) GetState(key common.Hash) common.Hash { func (s *StateObject) GetState(key common.Hash) common.Hash {
// If we have a dirty value for this state entry, return it // If we have a dirty value for this state entry, return it
value, dirty := s.dirtyStorage[key] value, dirty := s.dirtyStorage[key]
if dirty { if dirty {
@ -167,7 +167,7 @@ func (s *stateObject) GetState(key common.Hash) common.Hash {
} }
// GetCommittedState retrieves a value from the committed account storage trie. // GetCommittedState retrieves a value from the committed account storage trie.
func (s *stateObject) GetCommittedState(key common.Hash) common.Hash { func (s *StateObject) GetCommittedState(key common.Hash) common.Hash {
// If we have a pending write or clean cached, return that // If we have a pending write or clean cached, return that
if value, pending := s.pendingStorage[key]; pending { if value, pending := s.pendingStorage[key]; pending {
return value return value
@ -227,7 +227,7 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
} }
// SetState updates a value in account storage. // SetState updates a value in account storage.
func (s *stateObject) SetState(key, value common.Hash) { func (s *StateObject) SetState(key, value common.Hash) {
// If the new value is the same as old, don't set // If the new value is the same as old, don't set
prev := s.GetState(key) prev := s.GetState(key)
if prev == value { if prev == value {
@ -242,13 +242,13 @@ func (s *stateObject) SetState(key, value common.Hash) {
s.setState(key, value) s.setState(key, value)
} }
func (s *stateObject) setState(key, value common.Hash) { func (s *StateObject) setState(key, value common.Hash) {
s.dirtyStorage[key] = value s.dirtyStorage[key] = value
} }
// finalise moves all dirty storage slots into the pending area to be hashed or // finalise moves all dirty storage slots into the pending area to be hashed or
// committed later. It is invoked at the end of every transaction. // committed later. It is invoked at the end of every transaction.
func (s *stateObject) finalise(prefetch bool) { func (s *StateObject) finalise(prefetch bool) {
slotsToPrefetch := make([][]byte, 0, len(s.dirtyStorage)) slotsToPrefetch := make([][]byte, 0, len(s.dirtyStorage))
for key, value := range s.dirtyStorage { for key, value := range s.dirtyStorage {
s.pendingStorage[key] = value s.pendingStorage[key] = value
@ -270,7 +270,7 @@ func (s *stateObject) finalise(prefetch bool) {
// loading or updating of the trie, an error will be returned. Furthermore, // loading or updating of the trie, an error will be returned. Furthermore,
// this function will return the mutated storage trie, or nil if there is no // this function will return the mutated storage trie, or nil if there is no
// storage change at all. // storage change at all.
func (s *stateObject) updateTrie() (Trie, error) { func (s *StateObject) updateTrie() (Trie, error) {
// Make sure all dirty slots are finalized into the pending storage area // Make sure all dirty slots are finalized into the pending storage area
s.finalise(false) s.finalise(false)
@ -358,7 +358,7 @@ func (s *stateObject) updateTrie() (Trie, error) {
// updateRoot flushes all cached storage mutations to trie, recalculating the // updateRoot flushes all cached storage mutations to trie, recalculating the
// new storage trie root. // new storage trie root.
func (s *stateObject) updateRoot() { func (s *StateObject) updateRoot() {
// Flush cached storage mutations into trie, short circuit if any error // Flush cached storage mutations into trie, short circuit if any error
// is occurred or there is not change in the trie. // is occurred or there is not change in the trie.
tr, err := s.updateTrie() tr, err := s.updateTrie()
@ -375,7 +375,7 @@ func (s *stateObject) updateRoot() {
// commit obtains a set of dirty storage trie nodes and updates the account data. // commit obtains a set of dirty storage trie nodes and updates the account data.
// The returned set can be nil if nothing to commit. This function assumes all // The returned set can be nil if nothing to commit. This function assumes all
// storage mutations have already been flushed into trie by updateRoot. // storage mutations have already been flushed into trie by updateRoot.
func (s *stateObject) commit() (*trienode.NodeSet, error) { func (s *StateObject) commit() (*trienode.NodeSet, error) {
// Short circuit if trie is not even loaded, don't bother with committing anything // Short circuit if trie is not even loaded, don't bother with committing anything
if s.trie == nil { if s.trie == nil {
s.origin = s.data.Copy() s.origin = s.data.Copy()
@ -401,7 +401,7 @@ func (s *stateObject) commit() (*trienode.NodeSet, error) {
// AddBalance adds amount to s's balance. // AddBalance adds amount to s's balance.
// It is used to add funds to the destination account of a transfer. // It is used to add funds to the destination account of a transfer.
func (s *stateObject) AddBalance(amount *big.Int) { func (s *StateObject) AddBalance(amount *big.Int) {
// EIP161: We must check emptiness for the objects such that the account // EIP161: We must check emptiness for the objects such that the account
// clearing (0,0,0 objects) can take effect. // clearing (0,0,0 objects) can take effect.
if amount.Sign() == 0 { if amount.Sign() == 0 {
@ -415,14 +415,14 @@ func (s *stateObject) AddBalance(amount *big.Int) {
// SubBalance removes amount from s's balance. // SubBalance removes amount from s's balance.
// It is used to remove funds from the origin account of a transfer. // It is used to remove funds from the origin account of a transfer.
func (s *stateObject) SubBalance(amount *big.Int) { func (s *StateObject) SubBalance(amount *big.Int) {
if amount.Sign() == 0 { if amount.Sign() == 0 {
return return
} }
s.SetBalance(new(big.Int).Sub(s.Balance(), amount)) s.SetBalance(new(big.Int).Sub(s.Balance(), amount))
} }
func (s *stateObject) SetBalance(amount *big.Int) { func (s *StateObject) SetBalance(amount *big.Int) {
s.db.journal.append(balanceChange{ s.db.journal.append(balanceChange{
account: &s.address, account: &s.address,
prev: new(big.Int).Set(s.data.Balance), prev: new(big.Int).Set(s.data.Balance),
@ -430,12 +430,12 @@ func (s *stateObject) SetBalance(amount *big.Int) {
s.setBalance(amount) s.setBalance(amount)
} }
func (s *stateObject) setBalance(amount *big.Int) { func (s *StateObject) setBalance(amount *big.Int) {
s.data.Balance = amount s.data.Balance = amount
} }
func (s *stateObject) deepCopy(db *StateDB) *stateObject { func (s *StateObject) deepCopy(db *StateDB) *StateObject {
obj := &stateObject{ obj := &StateObject{
db: db, db: db,
address: s.address, address: s.address,
addrHash: s.addrHash, addrHash: s.addrHash,
@ -460,12 +460,12 @@ func (s *stateObject) deepCopy(db *StateDB) *stateObject {
// //
// Address returns the address of the contract/account // Address returns the address of the contract/account
func (s *stateObject) Address() common.Address { func (s *StateObject) Address() common.Address {
return s.address return s.address
} }
// Code returns the contract code associated with this object, if any. // Code returns the contract code associated with this object, if any.
func (s *stateObject) Code() []byte { func (s *StateObject) Code() []byte {
if s.code != nil { if s.code != nil {
return s.code return s.code
} }
@ -483,7 +483,7 @@ func (s *stateObject) Code() []byte {
// CodeSize returns the size of the contract code associated with this object, // CodeSize returns the size of the contract code associated with this object,
// or zero if none. This method is an almost mirror of Code, but uses a cache // or zero if none. This method is an almost mirror of Code, but uses a cache
// inside the database to avoid loading codes seen recently. // inside the database to avoid loading codes seen recently.
func (s *stateObject) CodeSize() int { func (s *StateObject) CodeSize() int {
if s.code != nil { if s.code != nil {
return len(s.code) return len(s.code)
} }
@ -497,7 +497,7 @@ func (s *stateObject) CodeSize() int {
return size return size
} }
func (s *stateObject) SetCode(codeHash common.Hash, code []byte) { func (s *StateObject) SetCode(codeHash common.Hash, code []byte) {
prevcode := s.Code() prevcode := s.Code()
s.db.journal.append(codeChange{ s.db.journal.append(codeChange{
account: &s.address, account: &s.address,
@ -507,13 +507,13 @@ func (s *stateObject) SetCode(codeHash common.Hash, code []byte) {
s.setCode(codeHash, code) s.setCode(codeHash, code)
} }
func (s *stateObject) setCode(codeHash common.Hash, code []byte) { func (s *StateObject) setCode(codeHash common.Hash, code []byte) {
s.code = code s.code = code
s.data.CodeHash = codeHash[:] s.data.CodeHash = codeHash[:]
s.dirtyCode = true s.dirtyCode = true
} }
func (s *stateObject) SetNonce(nonce uint64) { func (s *StateObject) SetNonce(nonce uint64) {
s.db.journal.append(nonceChange{ s.db.journal.append(nonceChange{
account: &s.address, account: &s.address,
prev: s.data.Nonce, prev: s.data.Nonce,
@ -521,22 +521,22 @@ func (s *stateObject) SetNonce(nonce uint64) {
s.setNonce(nonce) s.setNonce(nonce)
} }
func (s *stateObject) setNonce(nonce uint64) { func (s *StateObject) setNonce(nonce uint64) {
s.data.Nonce = nonce s.data.Nonce = nonce
} }
func (s *stateObject) CodeHash() []byte { func (s *StateObject) CodeHash() []byte {
return s.data.CodeHash return s.data.CodeHash
} }
func (s *stateObject) Balance() *big.Int { func (s *StateObject) Balance() *big.Int {
return s.data.Balance return s.data.Balance
} }
func (s *stateObject) Nonce() uint64 { func (s *StateObject) Nonce() uint64 {
return s.data.Nonce return s.data.Nonce
} }
func (s *stateObject) Root() common.Hash { func (s *StateObject) Root() common.Hash {
return s.data.Root return s.data.Root
} }

View file

@ -246,7 +246,7 @@ func TestSnapshot2(t *testing.T) {
} }
} }
func compareStateObjects(so0, so1 *stateObject, t *testing.T) { func compareStateObjects(so0, so1 *StateObject, t *testing.T) {
if so0.Address() != so1.Address() { if so0.Address() != so1.Address() {
t.Fatalf("Address mismatch: have %v, want %v", so0.address, so1.address) t.Fatalf("Address mismatch: have %v, want %v", so0.address, so1.address)
} }

View file

@ -79,7 +79,7 @@ type StateDB struct {
// This map holds 'live' objects, which will get modified while processing // This map holds 'live' objects, which will get modified while processing
// a state transition. // a state transition.
stateObjects map[common.Address]*stateObject stateObjects map[common.Address]*StateObject
stateObjectsPending map[common.Address]struct{} // State objects finalized but not yet written to the trie stateObjectsPending map[common.Address]struct{} // State objects finalized but not yet written to the trie
stateObjectsDirty map[common.Address]struct{} // State objects modified in the current execution stateObjectsDirty map[common.Address]struct{} // State objects modified in the current execution
stateObjectsDestruct map[common.Address]*types.StateAccount // State objects destructed in the block along with its previous value stateObjectsDestruct map[common.Address]*types.StateAccount // State objects destructed in the block along with its previous value
@ -106,7 +106,7 @@ type StateDB struct {
preimages map[common.Hash][]byte preimages map[common.Hash][]byte
// Per-transaction access list // Per-transaction access list
accessList *accessList accessList *AccessList
// Transient storage // Transient storage
transientStorage transientStorage transientStorage transientStorage
@ -155,14 +155,14 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error)
storages: make(map[common.Hash]map[common.Hash][]byte), storages: make(map[common.Hash]map[common.Hash][]byte),
accountsOrigin: make(map[common.Address][]byte), accountsOrigin: make(map[common.Address][]byte),
storagesOrigin: make(map[common.Address]map[common.Hash][]byte), storagesOrigin: make(map[common.Address]map[common.Hash][]byte),
stateObjects: make(map[common.Address]*stateObject), stateObjects: make(map[common.Address]*StateObject),
stateObjectsPending: make(map[common.Address]struct{}), stateObjectsPending: make(map[common.Address]struct{}),
stateObjectsDirty: make(map[common.Address]struct{}), stateObjectsDirty: make(map[common.Address]struct{}),
stateObjectsDestruct: make(map[common.Address]*types.StateAccount), stateObjectsDestruct: make(map[common.Address]*types.StateAccount),
logs: make(map[common.Hash][]*types.Log), logs: make(map[common.Hash][]*types.Log),
preimages: make(map[common.Hash][]byte), preimages: make(map[common.Hash][]byte),
journal: newJournal(), journal: newJournal(),
accessList: newAccessList(), accessList: NewAccessList(),
transientStorage: newTransientStorage(), transientStorage: newTransientStorage(),
hasher: crypto.NewKeccakState(), hasher: crypto.NewKeccakState(),
} }
@ -172,6 +172,10 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error)
return sdb, nil return sdb, nil
} }
func (s *StateDB) GetPrecompileManager() any {
return nil
}
// StartPrefetcher initializes a new trie prefetcher to pull in nodes from the // StartPrefetcher initializes a new trie prefetcher to pull in nodes from the
// state trie concurrently while the state is mutated so that when we reach the // state trie concurrently while the state is mutated so that when we reach the
// commit phase, most of the needed data is already hot. // commit phase, most of the needed data is already hot.
@ -374,38 +378,38 @@ func (s *StateDB) HasSelfDestructed(addr common.Address) bool {
// AddBalance adds amount to the account associated with addr. // AddBalance adds amount to the account associated with addr.
func (s *StateDB) AddBalance(addr common.Address, amount *big.Int) { func (s *StateDB) AddBalance(addr common.Address, amount *big.Int) {
stateObject := s.GetOrNewStateObject(addr) StateObject := s.GetOrNewStateObject(addr)
if stateObject != nil { if StateObject != nil {
stateObject.AddBalance(amount) StateObject.AddBalance(amount)
} }
} }
// SubBalance subtracts amount from the account associated with addr. // SubBalance subtracts amount from the account associated with addr.
func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) { func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) {
stateObject := s.GetOrNewStateObject(addr) StateObject := s.GetOrNewStateObject(addr)
if stateObject != nil { if StateObject != nil {
stateObject.SubBalance(amount) StateObject.SubBalance(amount)
} }
} }
func (s *StateDB) SetBalance(addr common.Address, amount *big.Int) { func (s *StateDB) SetBalance(addr common.Address, amount *big.Int) {
stateObject := s.GetOrNewStateObject(addr) StateObject := s.GetOrNewStateObject(addr)
if stateObject != nil { if StateObject != nil {
stateObject.SetBalance(amount) StateObject.SetBalance(amount)
} }
} }
func (s *StateDB) SetNonce(addr common.Address, nonce uint64) { func (s *StateDB) SetNonce(addr common.Address, nonce uint64) {
stateObject := s.GetOrNewStateObject(addr) StateObject := s.GetOrNewStateObject(addr)
if stateObject != nil { if StateObject != nil {
stateObject.SetNonce(nonce) StateObject.SetNonce(nonce)
} }
} }
func (s *StateDB) SetCode(addr common.Address, code []byte) { func (s *StateDB) SetCode(addr common.Address, code []byte) {
stateObject := s.GetOrNewStateObject(addr) StateObject := s.GetOrNewStateObject(addr)
if stateObject != nil { if StateObject != nil {
stateObject.SetCode(crypto.Keccak256Hash(code), code) StateObject.SetCode(crypto.Keccak256Hash(code), code)
} }
} }
@ -499,7 +503,7 @@ func (s *StateDB) GetTransientState(addr common.Address, key common.Hash) common
// //
// updateStateObject writes the given object to the trie. // updateStateObject writes the given object to the trie.
func (s *StateDB) updateStateObject(obj *stateObject) { func (s *StateDB) updateStateObject(obj *StateObject) {
// Track the amount of time wasted on updating the account from the trie // Track the amount of time wasted on updating the account from the trie
if metrics.EnabledExpensive { if metrics.EnabledExpensive {
defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now()) defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now())
@ -531,7 +535,7 @@ func (s *StateDB) updateStateObject(obj *stateObject) {
} }
// deleteStateObject removes the given object from the state trie. // deleteStateObject removes the given object from the state trie.
func (s *StateDB) deleteStateObject(obj *stateObject) { func (s *StateDB) deleteStateObject(obj *StateObject) {
// Track the amount of time wasted on deleting the account from the trie // Track the amount of time wasted on deleting the account from the trie
if metrics.EnabledExpensive { if metrics.EnabledExpensive {
defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now()) defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now())
@ -546,7 +550,7 @@ func (s *StateDB) deleteStateObject(obj *stateObject) {
// getStateObject retrieves a state object given by the address, returning nil if // getStateObject retrieves a state object given by the address, returning nil if
// the object is not found or was deleted in this execution context. If you need // the object is not found or was deleted in this execution context. If you need
// to differentiate between non-existent/just-deleted, use getDeletedStateObject. // to differentiate between non-existent/just-deleted, use getDeletedStateObject.
func (s *StateDB) getStateObject(addr common.Address) *stateObject { func (s *StateDB) getStateObject(addr common.Address) *StateObject {
if obj := s.getDeletedStateObject(addr); obj != nil && !obj.deleted { if obj := s.getDeletedStateObject(addr); obj != nil && !obj.deleted {
return obj return obj
} }
@ -557,7 +561,7 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject {
// nil for a deleted state object, it returns the actual object with the deleted // nil for a deleted state object, it returns the actual object with the deleted
// flag set. This is needed by the state journal to revert to the correct s- // flag set. This is needed by the state journal to revert to the correct s-
// destructed object instead of wiping all knowledge about the state object. // destructed object instead of wiping all knowledge about the state object.
func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject { func (s *StateDB) getDeletedStateObject(addr common.Address) *StateObject {
// Prefer live objects if any is available // Prefer live objects if any is available
if obj := s.stateObjects[addr]; obj != nil { if obj := s.stateObjects[addr]; obj != nil {
return obj return obj
@ -610,12 +614,12 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
return obj return obj
} }
func (s *StateDB) setStateObject(object *stateObject) { func (s *StateDB) setStateObject(object *StateObject) {
s.stateObjects[object.Address()] = object s.stateObjects[object.Address()] = object
} }
// GetOrNewStateObject retrieves a state object or create a new state object if nil. // GetOrNewStateObject retrieves a state object or create a new state object if nil.
func (s *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { func (s *StateDB) GetOrNewStateObject(addr common.Address) *StateObject {
stateObject := s.getStateObject(addr) stateObject := s.getStateObject(addr)
if stateObject == nil { if stateObject == nil {
stateObject, _ = s.createObject(addr) stateObject, _ = s.createObject(addr)
@ -625,7 +629,7 @@ func (s *StateDB) GetOrNewStateObject(addr common.Address) *stateObject {
// createObject creates a new state object. If there is an existing account with // createObject creates a new state object. If there is an existing account with
// the given address, it is overwritten and returned as the second return value. // the given address, it is overwritten and returned as the second return value.
func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { func (s *StateDB) createObject(addr common.Address) (newobj, prev *StateObject) {
prev = s.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that! prev = s.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that!
newobj = newObject(s, addr, nil) newobj = newObject(s, addr, nil)
if prev == nil { if prev == nil {
@ -685,9 +689,8 @@ func (s *StateDB) CreateAccount(addr common.Address) {
} }
} }
// Copy creates a deep, independent copy of the state. // GetOrNewStateObject retrieves a state object or create a new state object if nil.
// Snapshots of the copied state cannot be applied to the copy. func (s *StateDB) Copy() StateDBI {
func (s *StateDB) Copy() *StateDB {
// Copy all the basic fields, initialize the memory ones // Copy all the basic fields, initialize the memory ones
state := &StateDB{ state := &StateDB{
db: s.db, db: s.db,
@ -697,7 +700,7 @@ func (s *StateDB) Copy() *StateDB {
storages: make(map[common.Hash]map[common.Hash][]byte), storages: make(map[common.Hash]map[common.Hash][]byte),
accountsOrigin: make(map[common.Address][]byte), accountsOrigin: make(map[common.Address][]byte),
storagesOrigin: make(map[common.Address]map[common.Hash][]byte), storagesOrigin: make(map[common.Address]map[common.Hash][]byte),
stateObjects: make(map[common.Address]*stateObject, len(s.journal.dirties)), stateObjects: make(map[common.Address]*StateObject, len(s.journal.dirties)),
stateObjectsPending: make(map[common.Address]struct{}, len(s.stateObjectsPending)), stateObjectsPending: make(map[common.Address]struct{}, len(s.stateObjectsPending)),
stateObjectsDirty: make(map[common.Address]struct{}, len(s.journal.dirties)), stateObjectsDirty: make(map[common.Address]struct{}, len(s.journal.dirties)),
stateObjectsDestruct: make(map[common.Address]*types.StateAccount, len(s.stateObjectsDestruct)), stateObjectsDestruct: make(map[common.Address]*types.StateAccount, len(s.stateObjectsDestruct)),
@ -1315,7 +1318,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) { func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) {
if rules.IsBerlin { if rules.IsBerlin {
// Clear out any leftover from previous executions // Clear out any leftover from previous executions
al := newAccessList() al := NewAccessList()
s.accessList = al s.accessList = al
al.AddAddress(sender) al.AddAddress(sender)

View file

@ -173,10 +173,10 @@ func TestCopy(t *testing.T) {
orig.Finalise(false) orig.Finalise(false)
// Copy the state // Copy the state
copy := orig.Copy() copy := orig.Copy().(*StateDB)
// Copy the copy state // Copy the copy state
ccopy := copy.Copy() ccopy := copy.Copy().(*StateDB)
// modify all in memory // modify all in memory
for i := byte(0); i < 255; i++ { for i := byte(0); i < 255; i++ {
@ -594,7 +594,7 @@ func TestCopyCommitCopy(t *testing.T) {
t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{})
} }
// Copy the non-committed state database and check pre/post commit balance // Copy the non-committed state database and check pre/post commit balance
copyOne := state.Copy() copyOne := state.Copy().(*StateDB)
if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42) t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42)
} }
@ -681,7 +681,7 @@ func TestCopyCopyCommitCopy(t *testing.T) {
t.Fatalf("first copy committed storage slot mismatch: have %x, want %x", val, common.Hash{}) t.Fatalf("first copy committed storage slot mismatch: have %x, want %x", val, common.Hash{})
} }
// Copy the copy and check the balance once more // Copy the copy and check the balance once more
copyTwo := copyOne.Copy() copyTwo := copyOne.Copy().(*StateDB)
if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42) t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42)
} }
@ -866,8 +866,8 @@ func TestStateDBAccessList(t *testing.T) {
memDb := rawdb.NewMemoryDatabase() memDb := rawdb.NewMemoryDatabase()
db := NewDatabase(memDb) db := NewDatabase(memDb)
state, _ := New(types.EmptyRootHash, db, nil) state, _ := New(common.Hash{}, db, nil)
state.accessList = newAccessList() state.accessList = NewAccessList()
verifyAddrs := func(astrings ...string) { verifyAddrs := func(astrings ...string) {
t.Helper() t.Helper()
@ -1018,7 +1018,7 @@ func TestStateDBAccessList(t *testing.T) {
} }
// Check the copy // Check the copy
// Make a copy // Make a copy
state = stateCopy1 state = stateCopy1.(*StateDB)
verifyAddrs("aa", "bb") verifyAddrs("aa", "bb")
verifySlots("bb", "01", "02") verifySlots("bb", "01", "02")
if got, exp := len(state.accessList.addresses), 2; got != exp { if got, exp := len(state.accessList.addresses), 2; got != exp {

View file

@ -47,7 +47,7 @@ func newStatePrefetcher(config *params.ChainConfig, bc *BlockChain, engine conse
// Prefetch processes the state changes according to the Ethereum rules by running // Prefetch processes the state changes according to the Ethereum rules by running
// the transaction messages using the statedb, but any changes are discarded. The // the transaction messages using the statedb, but any changes are discarded. The
// only goal is to pre-cache transaction signatures and state trie nodes. // only goal is to pre-cache transaction signatures and state trie nodes.
func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *atomic.Bool) { func (p *statePrefetcher) Prefetch(block *types.Block, statedb state.StateDBI, cfg vm.Config, interrupt *atomic.Bool) {
var ( var (
header = block.Header() header = block.Header()
gaspool = new(GasPool).AddGas(block.GasLimit()) gaspool = new(GasPool).AddGas(block.GasLimit())
@ -85,7 +85,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
// precacheTransaction attempts to apply a transaction to the given state database // precacheTransaction attempts to apply a transaction to the given state database
// and uses the input parameters for its environment. The goal is not to execute // and uses the input parameters for its environment. The goal is not to execute
// the transaction successfully, rather to warm up touched data slots. // the transaction successfully, rather to warm up touched data slots.
func precacheTransaction(msg *Message, config *params.ChainConfig, gaspool *GasPool, statedb *state.StateDB, header *types.Header, evm *vm.EVM) error { func precacheTransaction(msg *Message, config *params.ChainConfig, gaspool *GasPool, statedb state.StateDBI, header *types.Header, evm *vm.EVM) error {
// Update the evm with the new transaction context. // Update the evm with the new transaction context.
evm.Reset(NewEVMTxContext(msg), statedb) evm.Reset(NewEVMTxContext(msg), statedb)
// Add addresses to access list if applicable // Add addresses to access list if applicable

View file

@ -32,18 +32,23 @@ import (
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
type SPBlockchain interface {
ChainContext
consensus.ChainHeaderReader
}
// StateProcessor is a basic Processor, which takes care of transitioning // StateProcessor is a basic Processor, which takes care of transitioning
// state from one point to another. // state from one point to another.
// //
// StateProcessor implements Processor. // StateProcessor implements Processor.
type StateProcessor struct { type StateProcessor struct {
config *params.ChainConfig // Chain configuration options config *params.ChainConfig // Chain configuration options
bc *BlockChain // Canonical block chain bc SPBlockchain // Canonical block chain
engine consensus.Engine // Consensus engine used for block rewards engine consensus.Engine // Consensus engine used for block rewards
} }
// NewStateProcessor initialises a new StateProcessor. // NewStateProcessor initialises a new StateProcessor.
func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consensus.Engine) *StateProcessor { func NewStateProcessor(config *params.ChainConfig, bc SPBlockchain, engine consensus.Engine) *StateProcessor {
return &StateProcessor{ return &StateProcessor{
config: config, config: config,
bc: bc, bc: bc,
@ -58,7 +63,7 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consen
// Process returns the receipts and logs accumulated during the process and // Process returns the receipts and logs accumulated during the process and
// returns the amount of gas that was used in the process. If any of the // returns the amount of gas that was used in the process. If any of the
// transactions failed to execute due to insufficient gas it will return an error. // transactions failed to execute due to insufficient gas it will return an error.
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) { func (p *StateProcessor) Process(block *types.Block, statedb state.StateDBI, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) {
var ( var (
receipts types.Receipts receipts types.Receipts
usedGas = new(uint64) usedGas = new(uint64)
@ -105,7 +110,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
return receipts, allLogs, *usedGas, nil return receipts, allLogs, *usedGas, nil
} }
func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) { func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, statedb state.StateDBI, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) {
// Create a new context to be used in the EVM environment. // Create a new context to be used in the EVM environment.
txContext := NewEVMTxContext(msg) txContext := NewEVMTxContext(msg)
evm.Reset(txContext, statedb) evm.Reset(txContext, statedb)
@ -159,7 +164,7 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta
// and uses the input parameters for its environment. It returns the receipt // and uses the input parameters for its environment. It returns the receipt
// for the transaction, gas used and an error if the transaction failed, // for the transaction, gas used and an error if the transaction failed,
// indicating the block was invalid. // indicating the block was invalid.
func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) { func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb state.StateDBI, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) {
msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee) msg, err := TransactionToMessage(tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee)
if err != nil { if err != nil {
return nil, err return nil, err
@ -172,7 +177,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root // ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root
// contract. This method is exported to be used in tests. // contract. This method is exported to be used in tests.
func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *state.StateDB) { func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb state.StateDBI) {
// If EIP-4788 is enabled, we need to invoke the beaconroot storage contract with // If EIP-4788 is enabled, we need to invoke the beaconroot storage contract with
// the new root // the new root
msg := &Message{ msg := &Message{

View file

@ -402,7 +402,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
// Execute the preparatory steps for state transition which includes: // Execute the preparatory steps for state transition which includes:
// - prepare accessList(post-berlin) // - prepare accessList(post-berlin)
// - reset transient storage(eip 1153) // - reset transient storage(eip 1153)
st.state.Prepare(rules, msg.From, st.evm.Context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList) st.state.Prepare(rules, msg.From, st.evm.Context.Coinbase, msg.To, vm.ActivePrecompiles(st.evm, rules), msg.AccessList)
var ( var (
ret []byte ret []byte

View file

@ -299,7 +299,7 @@ type BlobPool struct {
chain BlockChain // Chain object to access the state through chain BlockChain // Chain object to access the state through
head *types.Header // Current head of the chain head *types.Header // Current head of the chain
state *state.StateDB // Current state at the head of the chain state state.StateDBI // Current state at the head of the chain
gasTip *uint256.Int // Currently accepted minimum gas tip gasTip *uint256.Int // Currently accepted minimum gas tip
lookup map[common.Hash]uint64 // Lookup table mapping hashes to tx billy entries lookup map[common.Hash]uint64 // Lookup table mapping hashes to tx billy entries

View file

@ -158,7 +158,7 @@ func (bt *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block
return nil return nil
} }
func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { func (bc *testBlockChain) StateAt(common.Hash) (state.StateDBI, error) {
return bc.statedb, nil return bc.statedb, nil
} }

View file

@ -40,5 +40,5 @@ type BlockChain interface {
GetBlock(hash common.Hash, number uint64) *types.Block GetBlock(hash common.Hash, number uint64) *types.Block
// StateAt returns a state database for a given root hash (generally the head). // StateAt returns a state database for a given root hash (generally the head).
StateAt(root common.Hash) (*state.StateDB, error) StateAt(root common.Hash) (state.StateDBI, error)
} }

View file

@ -119,7 +119,10 @@ type BlockChain interface {
GetBlock(hash common.Hash, number uint64) *types.Block GetBlock(hash common.Hash, number uint64) *types.Block
// StateAt returns a state database for a given root hash (generally the head). // StateAt returns a state database for a given root hash (generally the head).
StateAt(root common.Hash) (*state.StateDB, error) StateAt(root common.Hash) (state.StateDBI, error)
// StateAtBlockNumber returns a state database at the given block number.
StateAtBlockNumber(number uint64) (state.StateDBI, error)
} }
// Config are the configuration parameters of the transaction pool. // Config are the configuration parameters of the transaction pool.
@ -213,7 +216,7 @@ type LegacyPool struct {
mu sync.RWMutex mu sync.RWMutex
currentHead atomic.Pointer[types.Header] // Current head of the blockchain currentHead atomic.Pointer[types.Header] // Current head of the blockchain
currentState *state.StateDB // Current state in the blockchain head currentState state.StateDBI // Current state in the blockchain head
pendingNonces *noncer // Pending state tracking virtual nonces pendingNonces *noncer // Pending state tracking virtual nonces
locals *accountSet // Set of local transaction to exempt from eviction rules locals *accountSet // Set of local transaction to exempt from eviction rules
@ -1401,17 +1404,30 @@ func (pool *LegacyPool) reset(oldHead, newHead *types.Header) {
} }
} }
// Initialize the internal state to the current head // Initialize the internal state to the current head
// Initialize the internal state to the current head
if newHead == nil { if newHead == nil {
newHead = pool.chain.CurrentBlock() // Special case during testing newHead = pool.chain.CurrentBlock() // Special case during testing
} }
if newHead == nil {
newHead = &types.Header{
Number: big.NewInt(0),
}
}
statedb, err := pool.chain.StateAt(newHead.Root) statedb, err := pool.chain.StateAt(newHead.Root)
if err != nil { if err != nil {
log.Error("Failed to reset txpool state", "err", err) statedb, err = pool.chain.StateAtBlockNumber(newHead.Number.Uint64())
return if err != nil {
log.Warn("Failed to get new state", "err", err)
}
} }
pool.currentHead.Store(newHead) pool.currentHead.Store(newHead)
pool.currentState = statedb pool.currentState = statedb
pool.pendingNonces = newNoncer(statedb) if pool.currentState != nil {
pool.pendingNonces = newNoncer(statedb)
} else {
pool.pendingNonces = &noncer{}
}
// Inject any transactions discarded due to reorgs // Inject any transactions discarded due to reorgs
log.Debug("Reinjecting stale transactions", "count", len(reinject)) log.Debug("Reinjecting stale transactions", "count", len(reinject))

View file

@ -63,7 +63,7 @@ func init() {
type testBlockChain struct { type testBlockChain struct {
config *params.ChainConfig config *params.ChainConfig
gasLimit atomic.Uint64 gasLimit atomic.Uint64
statedb *state.StateDB statedb state.StateDBI
chainHeadFeed *event.Feed chainHeadFeed *event.Feed
} }
@ -88,7 +88,11 @@ func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block
return types.NewBlock(bc.CurrentBlock(), nil, nil, nil, trie.NewStackTrie(nil)) return types.NewBlock(bc.CurrentBlock(), nil, nil, nil, trie.NewStackTrie(nil))
} }
func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { func (bc *testBlockChain) StateAt(common.Hash) (state.StateDBI, error) {
return bc.statedb, nil
}
func (bc *testBlockChain) StateAtBlockNumber(uint64) (state.StateDBI, error) {
return bc.statedb, nil return bc.statedb, nil
} }
@ -246,7 +250,7 @@ type testChain struct {
// testChain.State() is used multiple times to reset the pending state. // testChain.State() is used multiple times to reset the pending state.
// when simulate is true it will create a state that indicates // when simulate is true it will create a state that indicates
// that tx0 and tx1 are included in the chain. // that tx0 and tx1 are included in the chain.
func (c *testChain) State() (*state.StateDB, error) { func (c *testChain) State() (state.StateDBI, error) {
// delay "state change" by one. The tx pool fetches the // delay "state change" by one. The tx pool fetches the
// state multiple times and by delaying it a bit we simulate // state multiple times and by delaying it a bit we simulate
// a state change between those fetches. // a state change between those fetches.

View file

@ -27,13 +27,13 @@ import (
// accounts in the pool, falling back to reading from a real state database if // accounts in the pool, falling back to reading from a real state database if
// an account is unknown. // an account is unknown.
type noncer struct { type noncer struct {
fallback *state.StateDB fallback state.StateDBI
nonces map[common.Address]uint64 nonces map[common.Address]uint64
lock sync.Mutex lock sync.Mutex
} }
// newNoncer creates a new virtual state database to track the pool nonces. // newNoncer creates a new virtual state database to track the pool nonces.
func newNoncer(statedb *state.StateDB) *noncer { func newNoncer(statedb state.StateDBI) *noncer {
return &noncer{ return &noncer{
fallback: statedb.Copy(), fallback: statedb.Copy(),
nonces: make(map[common.Address]uint64), nonces: make(map[common.Address]uint64),

View file

@ -169,7 +169,7 @@ func validateBlobSidecar(hashes []common.Hash, sidecar *types.BlobTxSidecar) err
// ValidationOptionsWithState define certain differences between stateful transaction // ValidationOptionsWithState define certain differences between stateful transaction
// validation across the different pools without having to duplicate those checks. // validation across the different pools without having to duplicate those checks.
type ValidationOptionsWithState struct { type ValidationOptionsWithState struct {
State *state.StateDB // State database to check nonces and balances against State state.StateDBI // State database to check nonces and balances against
// FirstNonceGap is an optional callback to retrieve the first nonce gap in // FirstNonceGap is an optional callback to retrieve the first nonce gap in
// the list of pooled transactions of a specific account. If this method is // the list of pooled transactions of a specific account. If this method is

View file

@ -33,7 +33,7 @@ type Validator interface {
// ValidateState validates the given statedb and optionally the receipts and // ValidateState validates the given statedb and optionally the receipts and
// gas used. // gas used.
ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error ValidateState(block *types.Block, state state.StateDBI, receipts types.Receipts, usedGas uint64) error
} }
// Prefetcher is an interface for pre-caching transaction signatures and state. // Prefetcher is an interface for pre-caching transaction signatures and state.
@ -41,7 +41,7 @@ type Prefetcher interface {
// Prefetch processes the state changes according to the Ethereum rules by running // Prefetch processes the state changes according to the Ethereum rules by running
// the transaction messages using the statedb, but any changes are discarded. The // the transaction messages using the statedb, but any changes are discarded. The
// only goal is to pre-cache transaction signatures and state trie nodes. // only goal is to pre-cache transaction signatures and state trie nodes.
Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *atomic.Bool) Prefetch(block *types.Block, statedb state.StateDBI, cfg vm.Config, interrupt *atomic.Bool)
} }
// Processor is an interface for processing blocks using a given initial state. // Processor is an interface for processing blocks using a given initial state.
@ -49,5 +49,5 @@ type Processor interface {
// Process processes the state changes according to the Ethereum rules by running // Process processes the state changes according to the Ethereum rules by running
// the transaction messages using the statedb and applying any rewards to both // the transaction messages using the statedb and applying any rewards to both
// the processor (coinbase) and any included uncles. // the processor (coinbase) and any included uncles.
Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) Process(block *types.Block, statedb state.StateDBI, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error)
} }

View file

@ -17,6 +17,7 @@
package vm package vm
import ( import (
"context"
"crypto/sha256" "crypto/sha256"
"encoding/binary" "encoding/binary"
"errors" "errors"
@ -38,8 +39,12 @@ import (
// requires a deterministic gas count based on the input size of the Run method of the // requires a deterministic gas count based on the input size of the Run method of the
// contract. // contract.
type PrecompiledContract interface { type PrecompiledContract interface {
RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use // RegistryKey returns the address at which the contract will be registered.
Run(input []byte) ([]byte, error) // Run runs the precompiled contract RegistryKey() common.Address
// RequiredGas calculates the contract static gas use.
RequiredGas(input []byte) uint64
// Run runs the precompiled contract with the given context.
Run(ctx context.Context, evm PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error)
} }
// PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum // PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum
@ -148,44 +153,39 @@ func init() {
} }
// ActivePrecompiles returns the precompiles enabled with the current configuration. // ActivePrecompiles returns the precompiles enabled with the current configuration.
func ActivePrecompiles(rules params.Rules) []common.Address { func ActivePrecompiles(evm *EVM, rules params.Rules) []common.Address {
var precompiles []common.Address
switch { switch {
case rules.IsCancun: case rules.IsCancun:
return PrecompiledAddressesCancun precompiles = append(precompiles, PrecompiledAddressesCancun...)
case rules.IsBerlin: case rules.IsBerlin:
return PrecompiledAddressesBerlin precompiles = append(precompiles, PrecompiledAddressesBerlin...)
case rules.IsIstanbul: case rules.IsIstanbul:
return PrecompiledAddressesIstanbul precompiles = append(precompiles, PrecompiledAddressesIstanbul...)
case rules.IsByzantium: case rules.IsByzantium:
return PrecompiledAddressesByzantium precompiles = append(precompiles, PrecompiledAddressesByzantium...)
default: default:
return PrecompiledAddressesHomestead precompiles = append(precompiles, PrecompiledAddressesHomestead...)
} }
}
// RunPrecompiledContract runs and evaluates the output of a precompiled contract. if evm != nil {
// It returns precompiles = append(precompiles, evm.PrecompileManager.GetActive(rules)...)
// - the returned bytes,
// - the _remaining_ gas,
// - any error that occurred
func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) {
gasCost := p.RequiredGas(input)
if suppliedGas < gasCost {
return nil, 0, ErrOutOfGas
} }
suppliedGas -= gasCost return precompiles
output, err := p.Run(input)
return output, suppliedGas, err
} }
// ECRECOVER implemented as a native contract. // ECRECOVER implemented as a native contract.
type ecrecover struct{} type ecrecover struct{}
func (c *ecrecover) RegistryKey() common.Address {
return common.BytesToAddress([]byte{1})
}
func (c *ecrecover) RequiredGas(input []byte) uint64 { func (c *ecrecover) RequiredGas(input []byte) uint64 {
return params.EcrecoverGas return params.EcrecoverGas
} }
func (c *ecrecover) Run(input []byte) ([]byte, error) { func (c *ecrecover) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
const ecRecoverInputLength = 128 const ecRecoverInputLength = 128
input = common.RightPadBytes(input, ecRecoverInputLength) input = common.RightPadBytes(input, ecRecoverInputLength)
@ -219,6 +219,10 @@ func (c *ecrecover) Run(input []byte) ([]byte, error) {
// SHA256 implemented as a native contract. // SHA256 implemented as a native contract.
type sha256hash struct{} type sha256hash struct{}
func (c *sha256hash) RegistryKey() common.Address {
return common.BytesToAddress([]byte{2})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
// //
// This method does not require any overflow checking as the input size gas costs // This method does not require any overflow checking as the input size gas costs
@ -226,7 +230,7 @@ type sha256hash struct{}
func (c *sha256hash) RequiredGas(input []byte) uint64 { func (c *sha256hash) RequiredGas(input []byte) uint64 {
return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas
} }
func (c *sha256hash) Run(input []byte) ([]byte, error) { func (c *sha256hash) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
h := sha256.Sum256(input) h := sha256.Sum256(input)
return h[:], nil return h[:], nil
} }
@ -234,6 +238,10 @@ func (c *sha256hash) Run(input []byte) ([]byte, error) {
// RIPEMD160 implemented as a native contract. // RIPEMD160 implemented as a native contract.
type ripemd160hash struct{} type ripemd160hash struct{}
func (c *ripemd160hash) RegistryKey() common.Address {
return common.BytesToAddress([]byte{3})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
// //
// This method does not require any overflow checking as the input size gas costs // This method does not require any overflow checking as the input size gas costs
@ -241,7 +249,7 @@ type ripemd160hash struct{}
func (c *ripemd160hash) RequiredGas(input []byte) uint64 { func (c *ripemd160hash) RequiredGas(input []byte) uint64 {
return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas
} }
func (c *ripemd160hash) Run(input []byte) ([]byte, error) { func (c *ripemd160hash) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
ripemd := ripemd160.New() ripemd := ripemd160.New()
ripemd.Write(input) ripemd.Write(input)
return common.LeftPadBytes(ripemd.Sum(nil), 32), nil return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
@ -250,6 +258,10 @@ func (c *ripemd160hash) Run(input []byte) ([]byte, error) {
// data copy implemented as a native contract. // data copy implemented as a native contract.
type dataCopy struct{} type dataCopy struct{}
func (c *dataCopy) RegistryKey() common.Address {
return common.BytesToAddress([]byte{4})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
// //
// This method does not require any overflow checking as the input size gas costs // This method does not require any overflow checking as the input size gas costs
@ -257,8 +269,8 @@ type dataCopy struct{}
func (c *dataCopy) RequiredGas(input []byte) uint64 { func (c *dataCopy) RequiredGas(input []byte) uint64 {
return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas
} }
func (c *dataCopy) Run(in []byte) ([]byte, error) { func (c *dataCopy) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
return common.CopyBytes(in), nil return input, nil
} }
// bigModExp implements a native big integer exponential modular operation. // bigModExp implements a native big integer exponential modular operation.
@ -266,6 +278,10 @@ type bigModExp struct {
eip2565 bool eip2565 bool
} }
func (c *bigModExp) RegistryKey() common.Address {
return common.BytesToAddress([]byte{5})
}
var ( var (
big0 = big.NewInt(0) big0 = big.NewInt(0)
big1 = big.NewInt(1) big1 = big.NewInt(1)
@ -286,10 +302,11 @@ var (
// modexpMultComplexity implements bigModexp multComplexity formula, as defined in EIP-198 // modexpMultComplexity implements bigModexp multComplexity formula, as defined in EIP-198
// //
// def mult_complexity(x): // def mult_complexity(x):
// if x <= 64: return x ** 2 //
// elif x <= 1024: return x ** 2 // 4 + 96 * x - 3072 // if x <= 64: return x ** 2
// else: return x ** 2 // 16 + 480 * x - 199680 // elif x <= 1024: return x ** 2 // 4 + 96 * x - 3072
// else: return x ** 2 // 16 + 480 * x - 199680
// //
// where is x is max(length_of_MODULUS, length_of_BASE) // where is x is max(length_of_MODULUS, length_of_BASE)
func modexpMultComplexity(x *big.Int) *big.Int { func modexpMultComplexity(x *big.Int) *big.Int {
@ -383,7 +400,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
return gas.Uint64() return gas.Uint64()
} }
func (c *bigModExp) Run(input []byte) ([]byte, error) { func (c *bigModExp) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
var ( var (
baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64() baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64()
expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64() expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64()
@ -458,12 +475,16 @@ func runBn256Add(input []byte) ([]byte, error) {
// Istanbul consensus rules. // Istanbul consensus rules.
type bn256AddIstanbul struct{} type bn256AddIstanbul struct{}
func (c *bn256AddIstanbul) RegistryKey() common.Address {
return common.BytesToAddress([]byte{6})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 { func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 {
return params.Bn256AddGasIstanbul return params.Bn256AddGasIstanbul
} }
func (c *bn256AddIstanbul) Run(input []byte) ([]byte, error) { func (c *bn256AddIstanbul) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
return runBn256Add(input) return runBn256Add(input)
} }
@ -471,12 +492,16 @@ func (c *bn256AddIstanbul) Run(input []byte) ([]byte, error) {
// conforming to Byzantium consensus rules. // conforming to Byzantium consensus rules.
type bn256AddByzantium struct{} type bn256AddByzantium struct{}
func (c *bn256AddByzantium) RegistryKey() common.Address {
return common.BytesToAddress([]byte{6})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 { func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 {
return params.Bn256AddGasByzantium return params.Bn256AddGasByzantium
} }
func (c *bn256AddByzantium) Run(input []byte) ([]byte, error) { func (c *bn256AddByzantium) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
return runBn256Add(input) return runBn256Add(input)
} }
@ -496,12 +521,16 @@ func runBn256ScalarMul(input []byte) ([]byte, error) {
// multiplication conforming to Istanbul consensus rules. // multiplication conforming to Istanbul consensus rules.
type bn256ScalarMulIstanbul struct{} type bn256ScalarMulIstanbul struct{}
func (c *bn256ScalarMulIstanbul) RegistryKey() common.Address {
return common.BytesToAddress([]byte{7})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 { func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 {
return params.Bn256ScalarMulGasIstanbul return params.Bn256ScalarMulGasIstanbul
} }
func (c *bn256ScalarMulIstanbul) Run(input []byte) ([]byte, error) { func (c *bn256ScalarMulIstanbul) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
return runBn256ScalarMul(input) return runBn256ScalarMul(input)
} }
@ -509,12 +538,16 @@ func (c *bn256ScalarMulIstanbul) Run(input []byte) ([]byte, error) {
// multiplication conforming to Byzantium consensus rules. // multiplication conforming to Byzantium consensus rules.
type bn256ScalarMulByzantium struct{} type bn256ScalarMulByzantium struct{}
func (c *bn256ScalarMulByzantium) RegistryKey() common.Address {
return common.BytesToAddress([]byte{7})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 { func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 {
return params.Bn256ScalarMulGasByzantium return params.Bn256ScalarMulGasByzantium
} }
func (c *bn256ScalarMulByzantium) Run(input []byte) ([]byte, error) { func (c *bn256ScalarMulByzantium) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
return runBn256ScalarMul(input) return runBn256ScalarMul(input)
} }
@ -564,12 +597,16 @@ func runBn256Pairing(input []byte) ([]byte, error) {
// conforming to Istanbul consensus rules. // conforming to Istanbul consensus rules.
type bn256PairingIstanbul struct{} type bn256PairingIstanbul struct{}
func (c *bn256PairingIstanbul) RegistryKey() common.Address {
return common.BytesToAddress([]byte{8})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 { func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 {
return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul
} }
func (c *bn256PairingIstanbul) Run(input []byte) ([]byte, error) { func (c *bn256PairingIstanbul) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
return runBn256Pairing(input) return runBn256Pairing(input)
} }
@ -577,17 +614,25 @@ func (c *bn256PairingIstanbul) Run(input []byte) ([]byte, error) {
// conforming to Byzantium consensus rules. // conforming to Byzantium consensus rules.
type bn256PairingByzantium struct{} type bn256PairingByzantium struct{}
func (c *bn256PairingByzantium) RegistryKey() common.Address {
return common.BytesToAddress([]byte{8})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 { func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 {
return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium
} }
func (c *bn256PairingByzantium) Run(input []byte) ([]byte, error) { func (c *bn256PairingByzantium) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
return runBn256Pairing(input) return runBn256Pairing(input)
} }
type blake2F struct{} type blake2F struct{}
func (c *blake2F) RegistryKey() common.Address {
return common.BytesToAddress([]byte{9})
}
func (c *blake2F) RequiredGas(input []byte) uint64 { func (c *blake2F) RequiredGas(input []byte) uint64 {
// If the input is malformed, we can't calculate the gas, return 0 and let the // If the input is malformed, we can't calculate the gas, return 0 and let the
// actual call choke and fault. // actual call choke and fault.
@ -608,7 +653,7 @@ var (
errBlake2FInvalidFinalFlag = errors.New("invalid final flag") errBlake2FInvalidFinalFlag = errors.New("invalid final flag")
) )
func (c *blake2F) Run(input []byte) ([]byte, error) { func (c *blake2F) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
// Make sure the input is valid (correct length and final flag) // Make sure the input is valid (correct length and final flag)
if len(input) != blake2FInputLength { if len(input) != blake2FInputLength {
return nil, errBlake2FInvalidInputLength return nil, errBlake2FInvalidInputLength
@ -657,12 +702,16 @@ var (
// bls12381G1Add implements EIP-2537 G1Add precompile. // bls12381G1Add implements EIP-2537 G1Add precompile.
type bls12381G1Add struct{} type bls12381G1Add struct{}
func (c *bls12381G1Add) RegistryKey() common.Address {
return common.BytesToAddress([]byte{10})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bls12381G1Add) RequiredGas(input []byte) uint64 { func (c *bls12381G1Add) RequiredGas(input []byte) uint64 {
return params.Bls12381G1AddGas return params.Bls12381G1AddGas
} }
func (c *bls12381G1Add) Run(input []byte) ([]byte, error) { func (c *bls12381G1Add) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
// Implements EIP-2537 G1Add precompile. // Implements EIP-2537 G1Add precompile.
// > G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each). // > G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each).
// > Output is an encoding of addition operation result - single G1 point (`128` bytes). // > Output is an encoding of addition operation result - single G1 point (`128` bytes).
@ -695,12 +744,16 @@ func (c *bls12381G1Add) Run(input []byte) ([]byte, error) {
// bls12381G1Mul implements EIP-2537 G1Mul precompile. // bls12381G1Mul implements EIP-2537 G1Mul precompile.
type bls12381G1Mul struct{} type bls12381G1Mul struct{}
func (c *bls12381G1Mul) RegistryKey() common.Address {
return common.BytesToAddress([]byte{11})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bls12381G1Mul) RequiredGas(input []byte) uint64 { func (c *bls12381G1Mul) RequiredGas(input []byte) uint64 {
return params.Bls12381G1MulGas return params.Bls12381G1MulGas
} }
func (c *bls12381G1Mul) Run(input []byte) ([]byte, error) { func (c *bls12381G1Mul) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
// Implements EIP-2537 G1Mul precompile. // Implements EIP-2537 G1Mul precompile.
// > G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). // > G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes).
// > Output is an encoding of multiplication operation result - single G1 point (`128` bytes). // > Output is an encoding of multiplication operation result - single G1 point (`128` bytes).
@ -731,6 +784,10 @@ func (c *bls12381G1Mul) Run(input []byte) ([]byte, error) {
// bls12381G1MultiExp implements EIP-2537 G1MultiExp precompile. // bls12381G1MultiExp implements EIP-2537 G1MultiExp precompile.
type bls12381G1MultiExp struct{} type bls12381G1MultiExp struct{}
func (c *bls12381G1MultiExp) RegistryKey() common.Address {
return common.BytesToAddress([]byte{12})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 { func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 {
// Calculate G1 point, scalar value pair length // Calculate G1 point, scalar value pair length
@ -750,7 +807,7 @@ func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 {
return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000 return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000
} }
func (c *bls12381G1MultiExp) Run(input []byte) ([]byte, error) { func (c *bls12381G1MultiExp) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
// Implements EIP-2537 G1MultiExp precompile. // Implements EIP-2537 G1MultiExp precompile.
// G1 multiplication call expects `160*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). // G1 multiplication call expects `160*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes).
// Output is an encoding of multiexponentiation operation result - single G1 point (`128` bytes). // Output is an encoding of multiexponentiation operation result - single G1 point (`128` bytes).
@ -788,12 +845,16 @@ func (c *bls12381G1MultiExp) Run(input []byte) ([]byte, error) {
// bls12381G2Add implements EIP-2537 G2Add precompile. // bls12381G2Add implements EIP-2537 G2Add precompile.
type bls12381G2Add struct{} type bls12381G2Add struct{}
func (c *bls12381G2Add) RegistryKey() common.Address {
return common.BytesToAddress([]byte{13})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bls12381G2Add) RequiredGas(input []byte) uint64 { func (c *bls12381G2Add) RequiredGas(input []byte) uint64 {
return params.Bls12381G2AddGas return params.Bls12381G2AddGas
} }
func (c *bls12381G2Add) Run(input []byte) ([]byte, error) { func (c *bls12381G2Add) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
// Implements EIP-2537 G2Add precompile. // Implements EIP-2537 G2Add precompile.
// > G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each). // > G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each).
// > Output is an encoding of addition operation result - single G2 point (`256` bytes). // > Output is an encoding of addition operation result - single G2 point (`256` bytes).
@ -826,12 +887,16 @@ func (c *bls12381G2Add) Run(input []byte) ([]byte, error) {
// bls12381G2Mul implements EIP-2537 G2Mul precompile. // bls12381G2Mul implements EIP-2537 G2Mul precompile.
type bls12381G2Mul struct{} type bls12381G2Mul struct{}
func (c *bls12381G2Mul) RegistryKey() common.Address {
return common.BytesToAddress([]byte{14})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bls12381G2Mul) RequiredGas(input []byte) uint64 { func (c *bls12381G2Mul) RequiredGas(input []byte) uint64 {
return params.Bls12381G2MulGas return params.Bls12381G2MulGas
} }
func (c *bls12381G2Mul) Run(input []byte) ([]byte, error) { func (c *bls12381G2Mul) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
// Implements EIP-2537 G2MUL precompile logic. // Implements EIP-2537 G2MUL precompile logic.
// > G2 multiplication call expects `288` bytes as an input that is interpreted as byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). // > G2 multiplication call expects `288` bytes as an input that is interpreted as byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes).
// > Output is an encoding of multiplication operation result - single G2 point (`256` bytes). // > Output is an encoding of multiplication operation result - single G2 point (`256` bytes).
@ -862,6 +927,10 @@ func (c *bls12381G2Mul) Run(input []byte) ([]byte, error) {
// bls12381G2MultiExp implements EIP-2537 G2MultiExp precompile. // bls12381G2MultiExp implements EIP-2537 G2MultiExp precompile.
type bls12381G2MultiExp struct{} type bls12381G2MultiExp struct{}
func (c *bls12381G2MultiExp) RegistryKey() common.Address {
return common.BytesToAddress([]byte{15})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 { func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 {
// Calculate G2 point, scalar value pair length // Calculate G2 point, scalar value pair length
@ -881,7 +950,7 @@ func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 {
return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000 return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000
} }
func (c *bls12381G2MultiExp) Run(input []byte) ([]byte, error) { func (c *bls12381G2MultiExp) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
// Implements EIP-2537 G2MultiExp precompile logic // Implements EIP-2537 G2MultiExp precompile logic
// > G2 multiplication call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). // > G2 multiplication call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes).
// > Output is an encoding of multiexponentiation operation result - single G2 point (`256` bytes). // > Output is an encoding of multiexponentiation operation result - single G2 point (`256` bytes).
@ -919,12 +988,16 @@ func (c *bls12381G2MultiExp) Run(input []byte) ([]byte, error) {
// bls12381Pairing implements EIP-2537 Pairing precompile. // bls12381Pairing implements EIP-2537 Pairing precompile.
type bls12381Pairing struct{} type bls12381Pairing struct{}
func (c *bls12381Pairing) RegistryKey() common.Address {
return common.BytesToAddress([]byte{16})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bls12381Pairing) RequiredGas(input []byte) uint64 { func (c *bls12381Pairing) RequiredGas(input []byte) uint64 {
return params.Bls12381PairingBaseGas + uint64(len(input)/384)*params.Bls12381PairingPerPairGas return params.Bls12381PairingBaseGas + uint64(len(input)/384)*params.Bls12381PairingPerPairGas
} }
func (c *bls12381Pairing) Run(input []byte) ([]byte, error) { func (c *bls12381Pairing) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
// Implements EIP-2537 Pairing precompile logic. // Implements EIP-2537 Pairing precompile logic.
// > Pairing call expects `384*k` bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure: // > Pairing call expects `384*k` bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure:
// > - `128` bytes of G1 point encoding // > - `128` bytes of G1 point encoding
@ -998,12 +1071,16 @@ func decodeBLS12381FieldElement(in []byte) ([]byte, error) {
// bls12381MapG1 implements EIP-2537 MapG1 precompile. // bls12381MapG1 implements EIP-2537 MapG1 precompile.
type bls12381MapG1 struct{} type bls12381MapG1 struct{}
func (c *bls12381MapG1) RegistryKey() common.Address {
return common.BytesToAddress([]byte{17})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bls12381MapG1) RequiredGas(input []byte) uint64 { func (c *bls12381MapG1) RequiredGas(input []byte) uint64 {
return params.Bls12381MapG1Gas return params.Bls12381MapG1Gas
} }
func (c *bls12381MapG1) Run(input []byte) ([]byte, error) { func (c *bls12381MapG1) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
// Implements EIP-2537 Map_To_G1 precompile. // Implements EIP-2537 Map_To_G1 precompile.
// > Field-to-curve call expects `64` bytes an an input that is interpreted as a an element of the base field. // > Field-to-curve call expects `64` bytes an an input that is interpreted as a an element of the base field.
// > Output of this call is `128` bytes and is G1 point following respective encoding rules. // > Output of this call is `128` bytes and is G1 point following respective encoding rules.
@ -1033,12 +1110,16 @@ func (c *bls12381MapG1) Run(input []byte) ([]byte, error) {
// bls12381MapG2 implements EIP-2537 MapG2 precompile. // bls12381MapG2 implements EIP-2537 MapG2 precompile.
type bls12381MapG2 struct{} type bls12381MapG2 struct{}
func (c *bls12381MapG2) RegistryKey() common.Address {
return common.BytesToAddress([]byte{18})
}
// RequiredGas returns the gas required to execute the pre-compiled contract. // RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bls12381MapG2) RequiredGas(input []byte) uint64 { func (c *bls12381MapG2) RequiredGas(input []byte) uint64 {
return params.Bls12381MapG2Gas return params.Bls12381MapG2Gas
} }
func (c *bls12381MapG2) Run(input []byte) ([]byte, error) { func (c *bls12381MapG2) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int) ([]byte, error) {
// Implements EIP-2537 Map_FP2_TO_G2 precompile logic. // Implements EIP-2537 Map_FP2_TO_G2 precompile logic.
// > Field-to-curve call expects `128` bytes an an input that is interpreted as a an element of the quadratic extension field. // > Field-to-curve call expects `128` bytes an an input that is interpreted as a an element of the quadratic extension field.
// > Output of this call is `256` bytes and is G2 point following respective encoding rules. // > Output of this call is `256` bytes and is G2 point following respective encoding rules.
@ -1072,6 +1153,10 @@ func (c *bls12381MapG2) Run(input []byte) ([]byte, error) {
return g.EncodePoint(r), nil return g.EncodePoint(r), nil
} }
func (b *kzgPointEvaluation) RegistryKey() common.Address {
return common.BytesToAddress([]byte{19})
}
// kzgPointEvaluation implements the EIP-4844 point evaluation precompile. // kzgPointEvaluation implements the EIP-4844 point evaluation precompile.
type kzgPointEvaluation struct{} type kzgPointEvaluation struct{}
@ -1093,7 +1178,7 @@ var (
) )
// Run executes the point evaluation precompile. // Run executes the point evaluation precompile.
func (b *kzgPointEvaluation) Run(input []byte) ([]byte, error) { func (b *kzgPointEvaluation) Run(_ context.Context, _ PrecompileEVM, input []byte, _ common.Address, _ *big.Int) ([]byte, error) {
if len(input) != blobVerifyInputLength { if len(input) != blobVerifyInputLength {
return nil, errBlobVerifyInvalidInputLength return nil, errBlobVerifyInvalidInputLength
} }

View file

@ -18,8 +18,10 @@ package vm
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"math/big"
"os" "os"
"testing" "testing"
"time" "time"
@ -93,6 +95,16 @@ var blake2FMalformedInputTests = []precompiledFailureTest{
}, },
} }
func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) {
gasCost := p.RequiredGas(input)
if suppliedGas < gasCost {
return nil, 0, ErrOutOfGas
}
suppliedGas -= gasCost
output, err := p.Run(context.Background(), nil, input, common.Address{}, new(big.Int))
return output, suppliedGas, err
}
func testPrecompiled(addr string, test precompiledTest, t *testing.T) { func testPrecompiled(addr string, test precompiledTest, t *testing.T) {
p := allPrecompiles[common.HexToAddress(addr)] p := allPrecompiles[common.HexToAddress(addr)]
in := common.Hex2Bytes(test.Input) in := common.Hex2Bytes(test.Input)

View file

@ -55,6 +55,7 @@ func ValidEip(eipNum int) bool {
_, ok := activators[eipNum] _, ok := activators[eipNum]
return ok return ok
} }
func ActivateableEips() []string { func ActivateableEips() []string {
var nums []string var nums []string
for k := range activators { for k := range activators {

View file

@ -17,6 +17,7 @@
package vm package vm
import ( import (
"errors"
"math/big" "math/big"
"sync/atomic" "sync/atomic"
@ -52,6 +53,9 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
precompiles = PrecompiledContractsHomestead precompiles = PrecompiledContractsHomestead
} }
p, ok := precompiles[addr] p, ok := precompiles[addr]
if p == nil || !ok {
p, ok = evm.PrecompileManager.Get(addr, &evm.chainRules)
}
return p, ok return p, ok
} }
@ -101,6 +105,8 @@ type EVM struct {
TxContext TxContext
// StateDB gives access to the underlying state // StateDB gives access to the underlying state
StateDB StateDB StateDB StateDB
// PrecompileManager finds and runs precompiled contracts
PrecompileManager PrecompileManager
// Depth is the current call stack // Depth is the current call stack
depth int depth int
@ -134,6 +140,12 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time),
} }
evm.interpreter = NewEVMInterpreter(evm) evm.interpreter = NewEVMInterpreter(evm)
if pm := statedb.GetPrecompileManager(); pm != nil {
evm.PrecompileManager = pm.(PrecompileManager)
} else {
evm.PrecompileManager = NewPrecompileManager()
}
return evm return evm
} }
@ -220,7 +232,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
} }
if isPrecompile { if isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas) ret, gas, err = evm.PrecompileManager.Run(evm, p, input, caller.Address(), value, gas, false)
} else { } else {
// Initialise a new contract and set the code that is to be used by the EVM. // Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only. // The contract is a scoped environment for this execution context only.
@ -242,7 +254,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
// when we're in homestead this also counts for code storage gas errors. // when we're in homestead this also counts for code storage gas errors.
if err != nil { if err != nil {
evm.StateDB.RevertToSnapshot(snapshot) evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted { if !errors.Is(err, ErrExecutionReverted) {
gas = 0 gas = 0
} }
// TODO: consider clearing up unused snapshots: // TODO: consider clearing up unused snapshots:
@ -283,7 +295,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
// It is allowed to call precompiles, even via delegatecall // It is allowed to call precompiles, even via delegatecall
if p, isPrecompile := evm.precompile(addr); isPrecompile { if p, isPrecompile := evm.precompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas) ret, gas, err = evm.PrecompileManager.Run(evm, p, input, caller.Address(), value, gas, false)
} else { } else {
addrCopy := addr addrCopy := addr
// Initialise a new contract and set the code that is to be used by the EVM. // Initialise a new contract and set the code that is to be used by the EVM.
@ -295,7 +307,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
} }
if err != nil { if err != nil {
evm.StateDB.RevertToSnapshot(snapshot) evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted { if !errors.Is(err, ErrExecutionReverted) {
gas = 0 gas = 0
} }
} }
@ -328,7 +340,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
// It is allowed to call precompiles, even via delegatecall // It is allowed to call precompiles, even via delegatecall
if p, isPrecompile := evm.precompile(addr); isPrecompile { if p, isPrecompile := evm.precompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas) ret, gas, err = evm.PrecompileManager.Run(evm, p, input, caller.Address(), new(big.Int), gas, false)
} else { } else {
addrCopy := addr addrCopy := addr
// Initialise a new contract and make initialise the delegate values // Initialise a new contract and make initialise the delegate values
@ -339,7 +351,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
} }
if err != nil { if err != nil {
evm.StateDB.RevertToSnapshot(snapshot) evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted { if !errors.Is(err, ErrExecutionReverted) {
gas = 0 gas = 0
} }
} }
@ -377,7 +389,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
} }
if p, isPrecompile := evm.precompile(addr); isPrecompile { if p, isPrecompile := evm.precompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas) ret, gas, err = evm.PrecompileManager.Run(evm, p, input, caller.Address(), new(big.Int), gas, true)
} else { } else {
// At this point, we use a copy of address. If we don't, the go compiler will // At this point, we use a copy of address. If we don't, the go compiler will
// leak the 'contract' to the outer scope, and make allocation for 'contract' // leak the 'contract' to the outer scope, and make allocation for 'contract'
@ -395,7 +407,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
} }
if err != nil { if err != nil {
evm.StateDB.RevertToSnapshot(snapshot) evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted { if !errors.Is(err, ErrExecutionReverted) {
gas = 0 gas = 0
} }
} }
@ -490,7 +502,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
// when we're in homestead this also counts for code storage gas errors. // when we're in homestead this also counts for code storage gas errors.
if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) { if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) {
evm.StateDB.RevertToSnapshot(snapshot) evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted { if !errors.Is(err, ErrExecutionReverted) {
contract.UseGas(contract.Gas) contract.UseGas(contract.Gas)
} }
} }
@ -523,3 +535,5 @@ func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *
// ChainConfig returns the environment's chain configuration // ChainConfig returns the environment's chain configuration
func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig } func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
func (evm *EVM) GetContext() *BlockContext { return &evm.Context }
func (evm *EVM) GetStateDB() StateDB { return evm.StateDB }

View file

@ -595,7 +595,7 @@ func TestOpTstore(t *testing.T) {
value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700") value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700")
) )
// Add a stateObject for the caller and the contract being called // Add a StateObject for the caller and the contract being called
statedb.CreateAccount(caller) statedb.CreateAccount(caller)
statedb.CreateAccount(to) statedb.CreateAccount(to)

View file

@ -20,64 +20,14 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
) )
// StateDB is an EVM database for full state querying. // StateDB is an EVM database for full state querying.
type StateDB interface { type StateDB interface {
CreateAccount(common.Address) state.StateDBI
SubBalance(common.Address, *big.Int)
AddBalance(common.Address, *big.Int)
GetBalance(common.Address) *big.Int
GetNonce(common.Address) uint64
SetNonce(common.Address, uint64)
GetCodeHash(common.Address) common.Hash
GetCode(common.Address) []byte
SetCode(common.Address, []byte)
GetCodeSize(common.Address) int
AddRefund(uint64)
SubRefund(uint64)
GetRefund() uint64
GetCommittedState(common.Address, common.Hash) common.Hash
GetState(common.Address, common.Hash) common.Hash
SetState(common.Address, common.Hash, common.Hash)
GetTransientState(addr common.Address, key common.Hash) common.Hash
SetTransientState(addr common.Address, key, value common.Hash)
SelfDestruct(common.Address)
HasSelfDestructed(common.Address) bool
Selfdestruct6780(common.Address)
// Exist reports whether the given account exists in state.
// Notably this should also return true for self-destructed accounts.
Exist(common.Address) bool
// Empty returns whether the given account is empty. Empty
// is defined according to EIP161 (balance = nonce = code = 0).
Empty(common.Address) bool
AddressInAccessList(addr common.Address) bool
SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool)
// AddAddressToAccessList adds the given address to the access list. This operation is safe to perform
// even if the feature/fork is not active yet
AddAddressToAccessList(addr common.Address)
// AddSlotToAccessList adds the given (address,slot) to the access list. This operation is safe to perform
// even if the feature/fork is not active yet
AddSlotToAccessList(addr common.Address, slot common.Hash)
Prepare(rules params.Rules, sender, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList)
RevertToSnapshot(int)
Snapshot() int
AddLog(*types.Log)
AddPreimage(common.Hash, []byte)
} }
// CallContext provides a basic interface for the EVM calling conventions. The EVM // CallContext provides a basic interface for the EVM calling conventions. The EVM
@ -92,3 +42,30 @@ type CallContext interface {
// Create creates a new contract // Create creates a new contract
Create(env *EVM, me ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error) Create(env *EVM, me ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error)
} }
type (
// PrecompileManager allows the EVM to execute a precompiled contract.
PrecompileManager interface {
// `Get` returns the precompiled contract at `addr`. Returns nil if no
// contract is found at `addr`.
Get(addr common.Address, rules *params.Rules) (PrecompiledContract, bool)
GetActive(params.Rules) []common.Address
// `Run` runs a precompiled contract and returns the remaining gas.
Run(evm PrecompileEVM, p PrecompiledContract, input []byte, caller common.Address,
value *big.Int, suppliedGas uint64, readonly bool,
) (ret []byte, remainingGas uint64, err error)
}
// PrecompileEVM is the interface through which stateful precompiles can call back into the EVM.
PrecompileEVM interface {
GetStateDB() StateDB
Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error)
StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error)
Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error)
Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error)
GetContext() *BlockContext
}
)

View file

@ -0,0 +1,61 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package vm
import (
"context"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
)
// precompileManager is used as a default PrecompileManager for the EVM.
type precompileManager struct {
}
// NewPrecompileManager returns a new PrecompileManager for the current chain rules.
func NewPrecompileManager() PrecompileManager {
return &precompileManager{}
}
// Get returns the precompiled contract deployed at the given address.
func (pm *precompileManager) Get(addr common.Address, rules *params.Rules) (PrecompiledContract, bool) {
return nil, false
}
// GetActive sets the chain rules on the precompile manager and returns the list of active
// precompile addresses.
func (pm *precompileManager) GetActive(rules params.Rules) []common.Address {
return nil
}
// Run runs the given precompiled contract with the given input data and returns the remaining gas.
func (pm *precompileManager) Run(
evm PrecompileEVM, p PrecompiledContract, input []byte,
caller common.Address, value *big.Int, suppliedGas uint64, _ bool,
) (ret []byte, remainingGas uint64, err error) {
gasCost := p.RequiredGas(input)
if gasCost > suppliedGas {
return nil, 0, ErrOutOfGas
}
suppliedGas -= gasCost
output, err := p.Run(context.Background(), evm, input, caller, value)
return output, suppliedGas, err
}

View file

@ -47,7 +47,7 @@ type Config struct {
BlobHashes []common.Hash BlobHashes []common.Hash
Random *common.Hash Random *common.Hash
State *state.StateDB State state.StateDBI
GetHashFn func(n uint64) common.Hash GetHashFn func(n uint64) common.Hash
} }
@ -102,7 +102,7 @@ func setDefaults(cfg *Config) {
// //
// Execute sets up an in-memory, temporary, environment for the execution of // Execute sets up an in-memory, temporary, environment for the execution of
// the given code. It makes sure that it's restored to its original state afterwards. // the given code. It makes sure that it's restored to its original state afterwards.
func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { func Execute(code, input []byte, cfg *Config) ([]byte, state.StateDBI, error) {
if cfg == nil { if cfg == nil {
cfg = new(Config) cfg = new(Config)
} }
@ -120,7 +120,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
// Execute the preparatory steps for state transition which includes: // Execute the preparatory steps for state transition which includes:
// - prepare accessList(post-berlin) // - prepare accessList(post-berlin)
// - reset transient storage(eip 1153) // - reset transient storage(eip 1153)
cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, &address, vm.ActivePrecompiles(rules), nil) cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, &address, vm.ActivePrecompiles(vmenv, rules), nil)
cfg.State.CreateAccount(address) cfg.State.CreateAccount(address)
// set the receiver's (the executing contract) code for execution. // set the receiver's (the executing contract) code for execution.
cfg.State.SetCode(address, code) cfg.State.SetCode(address, code)
@ -153,7 +153,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
// Execute the preparatory steps for state transition which includes: // Execute the preparatory steps for state transition which includes:
// - prepare accessList(post-berlin) // - prepare accessList(post-berlin)
// - reset transient storage(eip 1153) // - reset transient storage(eip 1153)
cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, nil, vm.ActivePrecompiles(rules), nil) cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, nil, vm.ActivePrecompiles(vmenv, rules), nil)
// Call the code with the given configuration. // Call the code with the given configuration.
code, address, leftOverGas, err := vmenv.Create( code, address, leftOverGas, err := vmenv.Create(
sender, sender,
@ -181,7 +181,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er
// Execute the preparatory steps for state transition which includes: // Execute the preparatory steps for state transition which includes:
// - prepare accessList(post-berlin) // - prepare accessList(post-berlin)
// - reset transient storage(eip 1153) // - reset transient storage(eip 1153)
statedb.Prepare(rules, cfg.Origin, cfg.Coinbase, &address, vm.ActivePrecompiles(rules), nil) statedb.Prepare(rules, cfg.Origin, cfg.Coinbase, &address, vm.ActivePrecompiles(vmenv, rules), nil)
// Call the code with the given configuration. // Call the code with the given configuration.
ret, leftOverGas, err := vmenv.Call( ret, leftOverGas, err := vmenv.Call(

View file

@ -186,7 +186,7 @@ func (b *EthAPIBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts)
return b.eth.miner.PendingBlockAndReceipts() return b.eth.miner.PendingBlockAndReceipts()
} }
func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (state.StateDBI, *types.Header, error) {
// Pending state is only known by the miner // Pending state is only known by the miner
if number == rpc.PendingBlockNumber { if number == rpc.PendingBlockNumber {
block, state := b.eth.miner.Pending() block, state := b.eth.miner.Pending()
@ -210,7 +210,7 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B
return stateDb, header, nil return stateDb, header, nil
} }
func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (state.StateDBI, *types.Header, error) {
if blockNr, ok := blockNrOrHash.Number(); ok { if blockNr, ok := blockNrOrHash.Number(); ok {
return b.StateAndHeaderByNumber(ctx, blockNr) return b.StateAndHeaderByNumber(ctx, blockNr)
} }
@ -249,7 +249,7 @@ func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
return nil return nil
} }
func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error) { func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state state.StateDBI, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error) {
if vmConfig == nil { if vmConfig == nil {
vmConfig = b.eth.blockchain.GetVMConfig() vmConfig = b.eth.blockchain.GetVMConfig()
} }
@ -263,6 +263,11 @@ func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *st
return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig), state.Error return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig), state.Error
} }
func (b *EthAPIBackend) GetBlockContext(ctx context.Context, header *types.Header) *vm.BlockContext {
blockContext := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
return &blockContext
}
func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
return b.eth.BlockChain().SubscribeRemovedLogsEvent(ch) return b.eth.BlockChain().SubscribeRemovedLogsEvent(ch)
} }
@ -408,10 +413,10 @@ func (b *EthAPIBackend) StartMining() error {
return b.eth.StartMining() return b.eth.StartMining()
} }
func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, tracers.StateReleaseFunc, error) { func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base state.StateDBI, readOnly bool, preferDisk bool) (state.StateDBI, tracers.StateReleaseFunc, error) {
return b.eth.stateAtBlock(ctx, block, reexec, base, readOnly, preferDisk) return b.eth.stateAtBlock(ctx, block, reexec, base, readOnly, preferDisk)
} }
func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, state.StateDBI, tracers.StateReleaseFunc, error) {
return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) return b.eth.stateAtTransaction(ctx, block, txIndex, reexec)
} }

View file

@ -28,7 +28,7 @@ import (
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
@ -134,7 +134,7 @@ const AccountRangeMaxResults = 256
// AccountRange enumerates all accounts in the given block and start point in paging request // AccountRange enumerates all accounts in the given block and start point in paging request
func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hexutil.Bytes, maxResults int, nocode, nostorage, incompletes bool) (state.IteratorDump, error) { func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hexutil.Bytes, maxResults int, nocode, nostorage, incompletes bool) (state.IteratorDump, error) {
var stateDb *state.StateDB var stateDb state.StateDBI
var err error var err error
if number, ok := blockNrOrHash.Number(); ok { if number, ok := blockNrOrHash.Number(); ok {
@ -229,7 +229,7 @@ func (api *DebugAPI) StorageRangeAt(ctx context.Context, blockNrOrHash rpc.Block
return storageRangeAt(statedb, block.Root(), contractAddress, keyStart, maxResult) return storageRangeAt(statedb, block.Root(), contractAddress, keyStart, maxResult)
} }
func storageRangeAt(statedb *state.StateDB, root common.Hash, address common.Address, start []byte, maxResult int) (StorageRangeResult, error) { func storageRangeAt(statedb state.StateDBI, root common.Hash, address common.Address, start []byte, maxResult int) (StorageRangeResult, error) {
storageRoot := statedb.GetStorageRoot(address) storageRoot := statedb.GetStorageRoot(address)
if storageRoot == types.EmptyRootHash || storageRoot == (common.Hash{}) { if storageRoot == types.EmptyRootHash || storageRoot == (common.Hash{}) {
return StorageRangeResult{}, nil // empty storage return StorageRangeResult{}, nil // empty storage

View file

@ -35,7 +35,7 @@ import (
var dumper = spew.ConfigState{Indent: " "} var dumper = spew.ConfigState{Indent: " "}
func accountRangeTest(t *testing.T, trie *state.Trie, statedb *state.StateDB, start common.Hash, requestedNum int, expectedNum int) state.IteratorDump { func accountRangeTest(t *testing.T, trie *state.Trie, statedb state.StateDBI, start common.Hash, requestedNum int, expectedNum int) state.IteratorDump {
result := statedb.IteratorDump(&state.DumpConfig{ result := statedb.IteratorDump(&state.DumpConfig{
SkipCode: true, SkipCode: true,
SkipStorage: true, SkipStorage: true,

View file

@ -44,9 +44,9 @@ import (
"github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/eth/protocols/snap" "github.com/ethereum/go-ethereum/eth/protocols/snap"
"github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/internal/shutdowncheck" "github.com/ethereum/go-ethereum/internal/shutdowncheck"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/miner"
@ -242,7 +242,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
} }
eth.miner = miner.New(eth, &config.Miner, eth.blockchain.Config(), eth.EventMux(), eth.engine, eth.isLocalBlock) eth.miner = miner.New(eth, &config.Miner, eth.blockchain.Config(), eth.EventMux(), eth.engine, eth.isLocalBlock)
eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData)) eth.miner.SetExtra(MakeExtraData(config.Miner.ExtraData))
eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil} eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), stack.Config().AllowUnprotectedTxs, eth, nil}
if eth.APIBackend.allowUnprotectedTxs { if eth.APIBackend.allowUnprotectedTxs {
@ -279,7 +279,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
return eth, nil return eth, nil
} }
func makeExtraData(extra []byte) []byte { func MakeExtraData(extra []byte) []byte {
if len(extra) == 0 { if len(extra) == 0 {
// create default extradata // create default extradata
extra, _ = rlp.EncodeToBytes([]interface{}{ extra, _ = rlp.EncodeToBytes([]interface{}{
@ -299,8 +299,7 @@ func makeExtraData(extra []byte) []byte {
// APIs return the collection of RPC services the ethereum package offers. // APIs return the collection of RPC services the ethereum package offers.
// NOTE, some of these services probably need to be moved to somewhere else. // NOTE, some of these services probably need to be moved to somewhere else.
func (s *Ethereum) APIs() []rpc.API { func (s *Ethereum) APIs() []rpc.API {
apis := ethapi.GetAPIs(s.APIBackend) apis := ethapi.GetAPIs(s.APIBackend, s.BlockChain())
// Append any APIs exposed explicitly by the consensus engine // Append any APIs exposed explicitly by the consensus engine
apis = append(apis, s.engine.APIs(s.BlockChain())...) apis = append(apis, s.engine.APIs(s.BlockChain())...)
@ -468,6 +467,7 @@ func (s *Ethereum) Miner() *miner.Miner { return s.miner }
func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager } func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager }
func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain }
func (s *Ethereum) MinerChain() miner.BlockChain { return s.blockchain }
func (s *Ethereum) TxPool() *txpool.TxPool { return s.txPool } func (s *Ethereum) TxPool() *txpool.TxPool { return s.txPool }
func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
func (s *Ethereum) Engine() consensus.Engine { return s.engine } func (s *Ethereum) Engine() consensus.Engine { return s.engine }

View file

@ -29,7 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
) )

View file

@ -545,7 +545,7 @@ func (es *EventSystem) lightFilterLogs(header *types.Header, addresses []common.
func (es *EventSystem) eventLoop() { func (es *EventSystem) eventLoop() {
// Ensure all subscriptions get cleaned up // Ensure all subscriptions get cleaned up
defer func() { defer func() {
es.txsSub.Unsubscribe() // es.txsSub.Unsubscribe()
es.logsSub.Unsubscribe() es.logsSub.Unsubscribe()
es.rmLogsSub.Unsubscribe() es.rmLogsSub.Unsubscribe()
es.pendingLogsSub.Unsubscribe() es.pendingLogsSub.Unsubscribe()

View file

@ -35,9 +35,9 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
) )

View file

@ -83,8 +83,8 @@ const (
minTrienodeHealThrottle = 1 minTrienodeHealThrottle = 1
// maxTrienodeHealThrottle is the maximum divisor for throttling trie node // maxTrienodeHealThrottle is the maximum divisor for throttling trie node
// heal requests to avoid overloading the local node and exessively expanding // heal requests to avoid overloading the local node and excessively expanding
// the state trie bedth wise. // the state trie breadth wise.
maxTrienodeHealThrottle = maxTrieRequestCount maxTrienodeHealThrottle = maxTrieRequestCount
// trienodeHealThrottleIncrease is the multiplier for the throttle when the // trienodeHealThrottleIncrease is the multiplier for the throttle when the

View file

@ -37,7 +37,7 @@ import (
// for releasing state. // for releasing state.
var noopReleaser = tracers.StateReleaseFunc(func() {}) var noopReleaser = tracers.StateReleaseFunc(func() {})
func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (statedb *state.StateDB, release tracers.StateReleaseFunc, err error) { func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec uint64, base state.StateDBI, readOnly bool, preferDisk bool) (statedb state.StateDBI, release tracers.StateReleaseFunc, err error) {
var ( var (
current *types.Block current *types.Block
database state.Database database state.Database
@ -174,7 +174,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
return statedb, func() { triedb.Dereference(block.Root()) }, nil return statedb, func() { triedb.Dereference(block.Root()) }, nil
} }
func (eth *Ethereum) pathState(block *types.Block) (*state.StateDB, func(), error) { func (eth *Ethereum) pathState(block *types.Block) (state.StateDBI, func(), error) {
// Check if the requested state is available in the live chain. // Check if the requested state is available in the live chain.
statedb, err := eth.blockchain.StateAt(block.Root()) statedb, err := eth.blockchain.StateAt(block.Root())
if err == nil { if err == nil {
@ -208,7 +208,7 @@ func (eth *Ethereum) pathState(block *types.Block) (*state.StateDB, func(), erro
// - preferDisk: This arg can be used by the caller to signal that even though the 'base' is // - 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 // provided, it would be preferable to start from a fresh state, if we have it
// on disk. // on disk.
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) { func (eth *Ethereum) stateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base state.StateDBI, readOnly bool, preferDisk bool) (statedb state.StateDBI, release tracers.StateReleaseFunc, err error) {
if eth.blockchain.TrieDB().Scheme() == rawdb.HashScheme { if eth.blockchain.TrieDB().Scheme() == rawdb.HashScheme {
return eth.hashState(ctx, block, reexec, base, readOnly, preferDisk) return eth.hashState(ctx, block, reexec, base, readOnly, preferDisk)
} }
@ -216,7 +216,7 @@ func (eth *Ethereum) stateAtBlock(ctx context.Context, block *types.Block, reexe
} }
// stateAtTransaction returns the execution environment of a certain transaction. // stateAtTransaction returns the execution environment of a certain transaction.
func (eth *Ethereum) stateAtTransaction(ctx context.Context, 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.StateDBI, tracers.StateReleaseFunc, error) {
// Short circuit if it's genesis block. // Short circuit if it's genesis block.
if block.NumberU64() == 0 { if block.NumberU64() == 0 {
return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis") return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis")
@ -240,13 +240,12 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
for idx, tx := range block.Transactions() { for idx, tx := range block.Transactions() {
// Assemble the transaction call message and return if the requested offset // Assemble the transaction call message and return if the requested offset
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil) context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
if idx == txIndex { if idx == txIndex {
return msg, context, statedb, release, nil return msg, context, statedb, release, nil
} }
// Not yet the searched for transaction, execute on top of the current state // Not yet the searched for transaction, execute on top of the current state
vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{}) vmenv, vmError := eth.APIBackend.GetEVM(ctx, msg, statedb, block.Header(), &vm.Config{}, &context)
statedb.SetTxContext(tx.Hash(), idx) statedb.SetTxContext(tx.Hash(), idx)
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
@ -254,6 +253,9 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
// Ensure any modifications are committed to the state // Ensure any modifications are committed to the state
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number())) statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
if err := vmError(); err != nil {
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("execution error: %v", err)
}
} }
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash()) return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
} }

View file

@ -36,8 +36,8 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@ -85,8 +85,8 @@ type Backend interface {
ChainConfig() *params.ChainConfig ChainConfig() *params.ChainConfig
Engine() consensus.Engine Engine() consensus.Engine
ChainDb() ethdb.Database ChainDb() ethdb.Database
StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base state.StateDBI, readOnly bool, preferDisk bool) (state.StateDBI, StateReleaseFunc, error)
StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, state.StateDBI, StateReleaseFunc, error)
} }
// API is the collection of tracing APIs exposed over the private debugging endpoint. // API is the collection of tracing APIs exposed over the private debugging endpoint.
@ -183,7 +183,7 @@ type txTraceResult struct {
// blockTraceTask represents a single block trace task when an entire chain is // blockTraceTask represents a single block trace task when an entire chain is
// being traced. // being traced.
type blockTraceTask struct { type blockTraceTask struct {
statedb *state.StateDB // Intermediate state prepped for tracing statedb state.StateDBI // Intermediate state prepped for tracing
block *types.Block // Block to trace the transactions from block *types.Block // Block to trace the transactions from
release StateReleaseFunc // The function to release the held resource for this task release StateReleaseFunc // The function to release the held resource for this task
results []*txTraceResult // Trace results produced by the task results []*txTraceResult // Trace results produced by the task
@ -200,7 +200,7 @@ type blockTraceResult struct {
// txTraceTask represents a single transaction trace task when an entire block // txTraceTask represents a single transaction trace task when an entire block
// is being traced. // is being traced.
type txTraceTask struct { type txTraceTask struct {
statedb *state.StateDB // Intermediate state prepped for tracing statedb state.StateDBI // Intermediate state prepped for tracing
index int // Transaction offset in the block index int // Transaction offset in the block
} }
@ -308,7 +308,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
number uint64 number uint64
traced uint64 traced uint64
failed error failed error
statedb *state.StateDB statedb state.StateDBI
release StateReleaseFunc release StateReleaseFunc
) )
// Ensure everything is properly cleaned up on any exit path // Ensure everything is properly cleaned up on any exit path
@ -626,7 +626,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
// traceBlockParallel is for tracers that have a high overhead (read JS tracers). One thread // traceBlockParallel is for tracers that have a high overhead (read JS tracers). One thread
// runs along and executes txes without tracing enabled to generate their prestate. // runs along and executes txes without tracing enabled to generate their prestate.
// Worker threads take the tasks and the prestate and trace them. // Worker threads take the tasks and the prestate and trace them.
func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, statedb *state.StateDB, config *TraceConfig) ([]*txTraceResult, error) { func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, statedb state.StateDBI, config *TraceConfig) ([]*txTraceResult, error) {
// Execute all the transaction contained within the block concurrently // Execute all the transaction contained within the block concurrently
var ( var (
txs = block.Transactions() txs = block.Transactions()
@ -922,7 +922,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
// traceTx configures a new tracer according to the provided configuration, and // traceTx configures a new tracer according to the provided configuration, and
// executes the given message in the provided environment. The return value will // executes the given message in the provided environment. The return value will
// be tracer dependent. // be tracer dependent.
func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb state.StateDBI, config *TraceConfig) (interface{}, error) {
var ( var (
tracer Tracer tracer Tracer
err error err error

View file

@ -39,8 +39,8 @@ import (
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
@ -139,7 +139,7 @@ func (b *testBackend) teardown() {
b.chain.Stop() b.chain.Stop()
} }
func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error) { func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base state.StateDBI, readOnly bool, preferDisk bool) (state.StateDBI, StateReleaseFunc, error) {
statedb, err := b.chain.StateAt(block.Root()) statedb, err := b.chain.StateAt(block.Root())
if err != nil { if err != nil {
return nil, nil, errStateNotFound return nil, nil, errStateNotFound
@ -155,7 +155,7 @@ func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reex
return statedb, release, nil return statedb, release, nil
} }
func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) { func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, state.StateDBI, StateReleaseFunc, error) {
parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1) parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1)
if parent == nil { if parent == nil {
return nil, vm.BlockContext{}, nil, nil, errBlockNotFound return nil, vm.BlockContext{}, nil, nil, errBlockNotFound

View file

@ -251,7 +251,7 @@ func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Addr
t.ctx["block"] = t.vm.ToValue(env.Context.BlockNumber.Uint64()) t.ctx["block"] = t.vm.ToValue(env.Context.BlockNumber.Uint64())
// Update list of precompiles based on current block // Update list of precompiles based on current block
rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time) rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time)
t.activePrecompiles = vm.ActivePrecompiles(rules) t.activePrecompiles = vm.ActivePrecompiles(env, rules)
} }
// CaptureState implements the Tracer interface to trace a single step of VM execution. // CaptureState implements the Tracer interface to trace a single step of VM execution.

View file

@ -32,8 +32,8 @@ type accessList map[common.Address]accessListSlots
// contract that an EVM contract execution touches. // contract that an EVM contract execution touches.
type accessListSlots map[common.Hash]struct{} type accessListSlots map[common.Hash]struct{}
// newAccessList creates a new accessList. // NewAccessList creates a new accessList.
func newAccessList() accessList { func NewAccessList() accessList {
return make(map[common.Address]accessListSlots) return make(map[common.Address]accessListSlots)
} }
@ -117,7 +117,7 @@ func NewAccessListTracer(acl types.AccessList, from, to common.Address, precompi
for _, addr := range precompiles { for _, addr := range precompiles {
excl[addr] = struct{}{} excl[addr] = struct{}{}
} }
list := newAccessList() list := NewAccessList()
for _, al := range acl { for _, al := range acl {
if _, ok := excl[al.Address]; !ok { if _, ok := excl[al.Address]; !ok {
list.addAddress(al.Address) list.addAddress(al.Address)

View file

@ -82,7 +82,7 @@ func (t *fourByteTracer) store(id []byte, size int) {
func (t *fourByteTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { func (t *fourByteTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
// Update list of precompiles based on current block // Update list of precompiles based on current block
rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time) rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time)
t.activePrecompiles = vm.ActivePrecompiles(rules) t.activePrecompiles = vm.ActivePrecompiles(env, rules)
// Save the outer calldata also // Save the outer calldata also
if len(input) >= 4 { if len(input) >= 4 {

View file

@ -148,7 +148,7 @@ func (t *flatCallTracer) CaptureStart(env *vm.EVM, from common.Address, to commo
t.tracer.CaptureStart(env, from, to, create, input, gas, value) t.tracer.CaptureStart(env, from, to, create, input, gas, value)
// Update list of precompiles based on current block // Update list of precompiles based on current block
rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time) rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time)
t.activePrecompiles = vm.ActivePrecompiles(rules) t.activePrecompiles = vm.ActivePrecompiles(env, rules)
} }
// CaptureEnd is called after the call finishes to finalize the tracing. // CaptureEnd is called after the call finishes to finalize the tracing.

View file

@ -732,14 +732,17 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
} }
// Create the accountProof. // Create the accountProof.
tr, err := trie.NewStateTrie(trie.StateTrieID(header.Root), state.Database().TrieDB()) // tr, err := trie.NewStateTrie(trie.StateTrieID(header.Root), state.Database().TrieDB())
if err != nil { // if err != nil {
return nil, err // return nil, err
} // }
var accountProof proofList
if err := tr.Prove(crypto.Keccak256(address.Bytes()), &accountProof); err != nil { // TODO: Support Proofs
return nil, err var accountProof proofList = make(proofList, 0)
} // if err := tr.Prove(crypto.Keccak256(address.Bytes()), &accountProof); err != nil {
// return nil, err
// }
return &AccountResult{ return &AccountResult{
Address: address, Address: address,
AccountProof: accountProof, AccountProof: accountProof,
@ -951,7 +954,7 @@ type OverrideAccount struct {
type StateOverride map[common.Address]OverrideAccount type StateOverride map[common.Address]OverrideAccount
// Apply overrides the fields of specified accounts into the given state. // Apply overrides the fields of specified accounts into the given state.
func (diff *StateOverride) Apply(state *state.StateDB) error { func (diff *StateOverride) Apply(state state.StateDBI) error {
if diff == nil { if diff == nil {
return nil return nil
} }
@ -959,6 +962,9 @@ func (diff *StateOverride) Apply(state *state.StateDB) error {
// Override account nonce. // Override account nonce.
if account.Nonce != nil { if account.Nonce != nil {
state.SetNonce(addr, uint64(*account.Nonce)) state.SetNonce(addr, uint64(*account.Nonce))
if err := state.Error(); err != nil {
return err
}
} }
// Override account(contract) code. // Override account(contract) code.
if account.Code != nil { if account.Code != nil {
@ -967,6 +973,9 @@ func (diff *StateOverride) Apply(state *state.StateDB) error {
// Override account balance. // Override account balance.
if account.Balance != nil { if account.Balance != nil {
state.SetBalance(addr, (*big.Int)(*account.Balance)) state.SetBalance(addr, (*big.Int)(*account.Balance))
if err := state.Error(); err != nil {
return err
}
} }
if account.State != nil && account.StateDiff != nil { if account.State != nil && account.StateDiff != nil {
return fmt.Errorf("account %s has both 'state' and 'stateDiff'", addr.Hex()) return fmt.Errorf("account %s has both 'state' and 'stateDiff'", addr.Hex())
@ -1060,7 +1069,7 @@ func (context *ChainContext) GetHeader(hash common.Hash, number uint64) *types.H
return header return header
} }
func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) { func doCall(ctx context.Context, b Backend, args TransactionArgs, state state.StateDBI, header *types.Header, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
if err := overrides.Apply(state); err != nil { if err := overrides.Apply(state); err != nil {
return nil, err return nil, err
} }
@ -1081,11 +1090,11 @@ func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.S
if err != nil { if err != nil {
return nil, err return nil, err
} }
blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil) blockCtx := b.GetBlockContext(ctx, header)
if blockOverrides != nil { if blockOverrides != nil {
blockOverrides.Apply(&blockCtx) blockOverrides.Apply(blockCtx)
} }
evm, vmError := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, &blockCtx) evm, vmError := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, blockCtx)
// Wait for the context to be done and cancel the evm. Even if the // Wait for the context to be done and cancel the evm. Even if the
// EVM has finished, cancelling may be done (repeatedly) // EVM has finished, cancelling may be done (repeatedly)
@ -1177,7 +1186,7 @@ func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrO
// executeEstimate is a helper that executes the transaction under a given gas limit and returns // executeEstimate is a helper that executes the transaction under a given gas limit and returns
// true if the transaction fails for a reason that might be related to not enough gas. A non-nil // true if the transaction fails for a reason that might be related to not enough gas. A non-nil
// error means execution failed due to reasons unrelated to the gas limit. // error means execution failed due to reasons unrelated to the gas limit.
func executeEstimate(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, gasCap uint64, gasLimit uint64) (bool, *core.ExecutionResult, error) { func executeEstimate(ctx context.Context, b Backend, args TransactionArgs, state state.StateDBI, header *types.Header, gasCap uint64, gasLimit uint64) (bool, *core.ExecutionResult, error) {
args.Gas = (*hexutil.Uint64)(&gasLimit) args.Gas = (*hexutil.Uint64)(&gasLimit)
result, err := doCall(ctx, b, args, state, header, nil, nil, 0, gasCap) result, err := doCall(ctx, b, args, state, header, nil, nil, 0, gasCap)
if err != nil { if err != nil {
@ -1309,6 +1318,11 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
hi = mid hi = mid
} }
} }
// TODO: FIGURE OUT WHY THIS HACK IS NEEDED THANKS
// bump the estimate gas by 20% for stateful precompiles
hi += uint64(float64(hi) * 0.2)
return hexutil.Uint64(hi), nil return hexutil.Uint64(hi), nil
} }
@ -1617,8 +1631,14 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
to = crypto.CreateAddress(args.from(), uint64(*args.Nonce)) to = crypto.CreateAddress(args.from(), uint64(*args.Nonce))
} }
isPostMerge := header.Difficulty.Cmp(common.Big0) == 0 isPostMerge := header.Difficulty.Cmp(common.Big0) == 0
rules := b.ChainConfig().Rules(header.Number, isPostMerge, header.Time)
// Retrieve the precompiles since they don't need to be added to the access list // Retrieve the precompiles since they don't need to be added to the access list
precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge, header.Time)) state, _, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if err != nil {
return nil, 0, nil, err
}
precompiles := vm.ActivePrecompiles(vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, state, b.ChainConfig(), vm.Config{}), rules) // TODO: use evm precompile manager instead
// Create an initial tracer // Create an initial tracer
prevTracer := logger.NewAccessListTracer(nil, args.from(), to, precompiles) prevTracer := logger.NewAccessListTracer(nil, args.from(), to, precompiles)

View file

@ -501,7 +501,7 @@ func (b testBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.
func (b testBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { func (b testBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) {
return b.chain.GetBlock(hash, uint64(number.Int64())).Body(), nil return b.chain.GetBlock(hash, uint64(number.Int64())).Body(), nil
} }
func (b testBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { func (b testBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (state.StateDBI, *types.Header, error) {
if number == rpc.PendingBlockNumber { if number == rpc.PendingBlockNumber {
panic("pending state not implemented") panic("pending state not implemented")
} }
@ -515,7 +515,7 @@ func (b testBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.Bloc
stateDb, err := b.chain.StateAt(header.Root) stateDb, err := b.chain.StateAt(header.Root)
return stateDb, header, err return stateDb, header, err
} }
func (b testBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { func (b testBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (state.StateDBI, *types.Header, error) {
if blockNr, ok := blockNrOrHash.Number(); ok { if blockNr, ok := blockNrOrHash.Number(); ok {
return b.StateAndHeaderByNumber(ctx, blockNr) return b.StateAndHeaderByNumber(ctx, blockNr)
} }
@ -536,7 +536,7 @@ func (b testBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
} }
return big.NewInt(1) return big.NewInt(1)
} }
func (b testBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockContext *vm.BlockContext) (*vm.EVM, func() error) { func (b testBackend) GetEVM(ctx context.Context, msg *core.Message, state state.StateDBI, header *types.Header, vmConfig *vm.Config, blockContext *vm.BlockContext) (*vm.EVM, func() error) {
vmError := func() error { return nil } vmError := func() error { return nil }
if vmConfig == nil { if vmConfig == nil {
vmConfig = b.chain.GetVMConfig() vmConfig = b.chain.GetVMConfig()
@ -548,6 +548,10 @@ func (b testBackend) GetEVM(ctx context.Context, msg *core.Message, state *state
} }
return vm.NewEVM(context, txContext, state, b.chain.Config(), *vmConfig), vmError return vm.NewEVM(context, txContext, state, b.chain.Config(), *vmConfig), vmError
} }
func (b testBackend) GetBlockContext(ctx context.Context, header *types.Header) *vm.BlockContext {
blockContext := core.NewEVMBlockContext(header, b.chain, nil)
return &blockContext
}
func (b testBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { func (b testBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
panic("implement me") panic("implement me")
} }

View file

@ -63,12 +63,13 @@ type Backend interface {
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error)
StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (state.StateDBI, *types.Header, error)
StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (state.StateDBI, *types.Header, error)
PendingBlockAndReceipts() (*types.Block, types.Receipts) PendingBlockAndReceipts() (*types.Block, types.Receipts)
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
GetTd(ctx context.Context, hash common.Hash) *big.Int GetTd(ctx context.Context, hash common.Hash) *big.Int
GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error) GetEVM(ctx context.Context, msg *core.Message, state state.StateDBI, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error)
GetBlockContext(ctx context.Context, header *types.Header) *vm.BlockContext
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription
@ -99,7 +100,7 @@ type Backend interface {
ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession)
} }
func GetAPIs(apiBackend Backend) []rpc.API { func GetAPIs(apiBackend Backend, chain core.ChainContext) []rpc.API {
nonceLock := new(AddrLocker) nonceLock := new(AddrLocker)
return []rpc.API{ return []rpc.API{
{ {

View file

@ -291,10 +291,10 @@ func (b *backendMock) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc
func (b *backendMock) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { func (b *backendMock) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) {
return nil, nil return nil, nil
} }
func (b *backendMock) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { func (b *backendMock) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (state.StateDBI, *types.Header, error) {
return nil, nil, nil return nil, nil, nil
} }
func (b *backendMock) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { func (b *backendMock) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (state.StateDBI, *types.Header, error) {
return nil, nil, nil return nil, nil, nil
} }
func (b *backendMock) PendingBlockAndReceipts() (*types.Block, types.Receipts) { return nil, nil } func (b *backendMock) PendingBlockAndReceipts() (*types.Block, types.Receipts) { return nil, nil }
@ -305,9 +305,12 @@ func (b *backendMock) GetLogs(ctx context.Context, blockHash common.Hash, number
return nil, nil return nil, nil
} }
func (b *backendMock) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil } func (b *backendMock) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil }
func (b *backendMock) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error) { func (b *backendMock) GetEVM(ctx context.Context, msg *core.Message, state state.StateDBI, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error) {
return nil, nil return nil, nil
} }
func (b *backendMock) GetBlockContext(ctx context.Context, header *types.Header) *vm.BlockContext {
return nil
}
func (b *backendMock) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { return nil } func (b *backendMock) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { return nil }
func (b *backendMock) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { func (b *backendMock) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
return nil return nil

View file

@ -51,6 +51,16 @@ func (s *senderFromServer) Sender(tx *types.Transaction) (common.Address, error)
return s.addr, nil return s.addr, nil
} }
func (s *senderFromServer) PubKey(tx *types.Transaction) ([]byte, error) {
// not implemented
return nil, nil
}
func (s *senderFromServer) Signature(tx *types.Transaction) ([]byte, error) {
// not implemented
return nil, nil
}
func (s *senderFromServer) ChainID() *big.Int { func (s *senderFromServer) ChainID() *big.Int {
panic("can't sign with senderFromServer") panic("can't sign with senderFromServer")
} }

View file

@ -35,7 +35,7 @@ import (
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
) )
@ -85,7 +85,7 @@ type Account struct {
} }
// getState fetches the StateDB object for an account. // getState fetches the StateDB object for an account.
func (a *Account) getState(ctx context.Context) (*state.StateDB, error) { func (a *Account) getState(ctx context.Context) (state.StateDBI, error) {
state, _, err := a.r.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash) state, _, err := a.r.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash)
return state, err return state, err
} }

View file

@ -25,7 +25,7 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/graph-gophers/graphql-go" "github.com/graph-gophers/graphql-go"

View file

@ -137,7 +137,7 @@ func (b *LesApiBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts)
return nil, nil return nil, nil
} }
func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (state.StateDBI, *types.Header, error) {
header, err := b.HeaderByNumber(ctx, number) header, err := b.HeaderByNumber(ctx, number)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -148,7 +148,7 @@ func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B
return light.NewState(ctx, header, b.eth.odr), header, nil return light.NewState(ctx, header, b.eth.odr), header, nil
} }
func (b *LesApiBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { func (b *LesApiBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (state.StateDBI, *types.Header, error) {
if blockNr, ok := blockNrOrHash.Number(); ok { if blockNr, ok := blockNrOrHash.Number(); ok {
return b.StateAndHeaderByNumber(ctx, blockNr) return b.StateAndHeaderByNumber(ctx, blockNr)
} }
@ -183,7 +183,7 @@ func (b *LesApiBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
return nil return nil
} }
func (b *LesApiBackend) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error) { func (b *LesApiBackend) GetEVM(ctx context.Context, msg *core.Message, state state.StateDBI, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error) {
if vmConfig == nil { if vmConfig == nil {
vmConfig = new(vm.Config) vmConfig = new(vm.Config)
} }
@ -195,6 +195,11 @@ func (b *LesApiBackend) GetEVM(ctx context.Context, msg *core.Message, state *st
return vm.NewEVM(context, txContext, state, b.eth.chainConfig, *vmConfig), state.Error return vm.NewEVM(context, txContext, state, b.eth.chainConfig, *vmConfig), state.Error
} }
func (b *LesApiBackend) GetBlockContext(_ context.Context, header *types.Header) *vm.BlockContext {
blockContext := core.NewEVMBlockContext(header, b.eth.blockchain, nil)
return &blockContext
}
func (b *LesApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { func (b *LesApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
return b.eth.txPool.Add(ctx, signedTx) return b.eth.txPool.Add(ctx, signedTx)
} }
@ -328,10 +333,10 @@ func (b *LesApiBackend) CurrentHeader() *types.Header {
return b.eth.blockchain.CurrentHeader() return b.eth.blockchain.CurrentHeader()
} }
func (b *LesApiBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, tracers.StateReleaseFunc, error) { func (b *LesApiBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base state.StateDBI, readOnly bool, preferDisk bool) (state.StateDBI, tracers.StateReleaseFunc, error) {
return b.eth.stateAtBlock(ctx, block, reexec) return b.eth.stateAtBlock(ctx, block, reexec)
} }
func (b *LesApiBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { func (b *LesApiBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, state.StateDBI, tracers.StateReleaseFunc, error) {
return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) return b.eth.stateAtTransaction(ctx, block, txIndex, reexec)
} }

View file

@ -33,8 +33,8 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/internal/shutdowncheck" "github.com/ethereum/go-ethereum/internal/shutdowncheck"
"github.com/ethereum/go-ethereum/les/vflux" "github.com/ethereum/go-ethereum/les/vflux"
vfc "github.com/ethereum/go-ethereum/les/vflux/client" vfc "github.com/ethereum/go-ethereum/les/vflux/client"
@ -288,7 +288,7 @@ func (s *LightDummyAPI) Mining() bool {
// APIs returns the collection of RPC services the ethereum package offers. // APIs returns the collection of RPC services the ethereum package offers.
// NOTE, some of these services probably need to be moved to somewhere else. // NOTE, some of these services probably need to be moved to somewhere else.
func (s *LightEthereum) APIs() []rpc.API { func (s *LightEthereum) APIs() []rpc.API {
apis := ethapi.GetAPIs(s.ApiBackend) apis := ethapi.GetAPIs(s.ApiBackend, s.BlockChain())
apis = append(apis, s.engine.APIs(s.BlockChain().HeaderChain())...) apis = append(apis, s.engine.APIs(s.BlockChain().HeaderChain())...)
return append(apis, []rpc.API{ return append(apis, []rpc.API{
{ {

View file

@ -98,7 +98,7 @@ func odrAccounts(ctx context.Context, db ethdb.Database, config *params.ChainCon
var ( var (
res []byte res []byte
st *state.StateDB st state.StateDBI
err error err error
) )
for _, addr := range acc { for _, addr := range acc {

View file

@ -34,12 +34,12 @@ import (
var noopReleaser = tracers.StateReleaseFunc(func() {}) var noopReleaser = tracers.StateReleaseFunc(func() {})
// stateAtBlock retrieves the state database associated with a certain block. // stateAtBlock retrieves the state database associated with a certain block.
func (leth *LightEthereum) stateAtBlock(ctx context.Context, block *types.Block, reexec uint64) (*state.StateDB, tracers.StateReleaseFunc, error) { func (leth *LightEthereum) stateAtBlock(ctx context.Context, block *types.Block, reexec uint64) (state.StateDBI, tracers.StateReleaseFunc, error) {
return light.NewState(ctx, block.Header(), leth.odr), noopReleaser, nil return light.NewState(ctx, block.Header(), leth.odr), noopReleaser, nil
} }
// stateAtTransaction returns the execution environment of a certain transaction. // stateAtTransaction returns the execution environment of a certain transaction.
func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, state.StateDBI, tracers.StateReleaseFunc, error) {
// Short circuit if it's genesis block. // Short circuit if it's genesis block.
if block.NumberU64() == 0 { if block.NumberU64() == 0 {
return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis") return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis")

View file

@ -156,7 +156,7 @@ func odrAccounts(ctx context.Context, db ethdb.Database, bc *core.BlockChain, lc
dummyAddr := common.HexToAddress("1234567812345678123456781234567812345678") dummyAddr := common.HexToAddress("1234567812345678123456781234567812345678")
acc := []common.Address{testBankAddress, acc1Addr, acc2Addr, dummyAddr} acc := []common.Address{testBankAddress, acc1Addr, acc2Addr, dummyAddr}
var st *state.StateDB var st state.StateDBI
if bc == nil { if bc == nil {
header := lc.GetHeaderByHash(bhash) header := lc.GetHeaderByHash(bhash)
st = NewState(ctx, header, lc.Odr()) st = NewState(ctx, header, lc.Odr())
@ -185,7 +185,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
data[35] = byte(i) data[35] = byte(i)
var ( var (
st *state.StateDB st state.StateDBI
header *types.Header header *types.Header
chain core.ChainContext chain core.ChainContext
) )

View file

@ -36,7 +36,7 @@ var (
sha3Nil = crypto.Keccak256Hash(nil) sha3Nil = crypto.Keccak256Hash(nil)
) )
func NewState(ctx context.Context, head *types.Header, odr OdrBackend) *state.StateDB { func NewState(ctx context.Context, head *types.Header, odr OdrBackend) state.StateDBI {
state, _ := state.New(head.Root, NewStateDatabase(ctx, head, odr), nil) state, _ := state.New(head.Root, NewStateDatabase(ctx, head, odr), nil)
return state return state
} }

View file

@ -114,7 +114,7 @@ func NewTxPool(config *params.ChainConfig, chain *LightChain, relay TxRelayBacke
} }
// currentState returns the light state of the current head header // currentState returns the light state of the current head header
func (pool *TxPool) currentState(ctx context.Context) *state.StateDB { func (pool *TxPool) currentState(ctx context.Context) state.StateDBI {
return NewState(ctx, pool.chain.CurrentHeader(), pool.odr) return NewState(ctx, pool.chain.CurrentHeader(), pool.odr)
} }

View file

@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
@ -39,10 +40,23 @@ import (
// Backend wraps all methods required for mining. Only full node is capable // Backend wraps all methods required for mining. Only full node is capable
// to offer all the functions here. // to offer all the functions here.
type Backend interface { type Backend interface {
BlockChain() *core.BlockChain MinerChain() BlockChain
TxPool() *txpool.TxPool TxPool() *txpool.TxPool
} }
type BlockChain interface {
GetVMConfig() *vm.Config
Engine() consensus.Engine
CurrentBlock() *types.Header
StateAt(common.Hash) (state.StateDBI, error)
StateAtBlockNumber(uint64) (state.StateDBI, error)
GetBlockByHash(common.Hash) *types.Block
consensus.ChainHeaderReader
HasBlock(common.Hash, uint64) bool
SubscribeChainHeadEvent(chan<- core.ChainHeadEvent) event.Subscription
WriteBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state state.StateDBI, emitHeadEvent bool) (status core.WriteStatus, err error)
}
// Config is the configuration parameters of mining. // Config is the configuration parameters of mining.
type Config struct { type Config struct {
Etherbase common.Address `toml:",omitempty"` // Public address for block mining rewards Etherbase common.Address `toml:",omitempty"` // Public address for block mining rewards
@ -204,7 +218,7 @@ func (miner *Miner) SetRecommitInterval(interval time.Duration) {
// Pending returns the currently pending block and associated state. The returned // Pending returns the currently pending block and associated state. The returned
// values can be nil in case the pending block is not initialized // values can be nil in case the pending block is not initialized
func (miner *Miner) Pending() (*types.Block, *state.StateDB) { func (miner *Miner) Pending() (*types.Block, state.StateDBI) {
return miner.worker.pending() return miner.worker.pending()
} }

View file

@ -40,7 +40,7 @@ import (
) )
type mockBackend struct { type mockBackend struct {
bc *core.BlockChain bc BlockChain
txPool *txpool.TxPool txPool *txpool.TxPool
} }
@ -51,7 +51,11 @@ func NewMockBackend(bc *core.BlockChain, txPool *txpool.TxPool) *mockBackend {
} }
} }
func (m *mockBackend) BlockChain() *core.BlockChain { func (m *mockBackend) BlockChain() BlockChain {
return m.bc
}
func (m *mockBackend) MinerChain() BlockChain {
return m.bc return m.bc
} }
@ -59,14 +63,14 @@ func (m *mockBackend) TxPool() *txpool.TxPool {
return m.txPool return m.txPool
} }
func (m *mockBackend) StateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) { func (m *mockBackend) StateAtBlock(block *types.Block, reexec uint64, base state.StateDBI, checkLive bool, preferDisk bool) (statedb state.StateDBI, err error) {
return nil, errors.New("not supported") return nil, errors.New("not supported")
} }
type testBlockChain struct { type testBlockChain struct {
root common.Hash root common.Hash
config *params.ChainConfig config *params.ChainConfig
statedb *state.StateDB statedb state.StateDBI
gasLimit uint64 gasLimit uint64
chainHeadFeed *event.Feed chainHeadFeed *event.Feed
} }
@ -86,7 +90,11 @@ func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block
return types.NewBlock(bc.CurrentBlock(), nil, nil, nil, trie.NewStackTrie(nil)) return types.NewBlock(bc.CurrentBlock(), nil, nil, nil, trie.NewStackTrie(nil))
} }
func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { func (bc *testBlockChain) StateAt(common.Hash) (state.StateDBI, error) {
return bc.statedb, nil
}
func (bc *testBlockChain) StateAtBlockNumber(uint64) (state.StateDBI, error) {
return bc.statedb, nil return bc.statedb, nil
} }

View file

@ -80,22 +80,22 @@ func (s *txByPriceAndTime) Pop() interface{} {
return x return x
} }
// transactionsByPriceAndNonce represents a set of transactions that can return // TransactionsByPriceAndNonce represents a set of transactions that can return
// transactions in a profit-maximizing sorted order, while supporting removing // transactions in a profit-maximizing sorted order, while supporting removing
// entire batches of transactions for non-executable accounts. // entire batches of transactions for non-executable accounts.
type transactionsByPriceAndNonce struct { type TransactionsByPriceAndNonce struct {
txs map[common.Address][]*txpool.LazyTransaction // Per account nonce-sorted list of transactions txs map[common.Address][]*txpool.LazyTransaction // Per account nonce-sorted list of transactions
heads txByPriceAndTime // Next transaction for each unique account (price heap) heads txByPriceAndTime // Next transaction for each unique account (price heap)
signer types.Signer // Signer for the set of transactions signer types.Signer // Signer for the set of transactions
baseFee *big.Int // Current base fee baseFee *big.Int // Current base fee
} }
// newTransactionsByPriceAndNonce creates a transaction set that can retrieve // NewTransactionsByPriceAndNonce creates a transaction set that can retrieve
// price sorted transactions in a nonce-honouring way. // price sorted transactions in a nonce-honouring way.
// //
// Note, the input map is reowned so the caller should not interact any more with // Note, the input map is reowned so the caller should not interact any more with
// if after providing it to the constructor. // if after providing it to the constructor.
func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address][]*txpool.LazyTransaction, baseFee *big.Int) *transactionsByPriceAndNonce { func NewTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address][]*txpool.LazyTransaction, baseFee *big.Int) *TransactionsByPriceAndNonce {
// Initialize a price and received time based heap with the head transactions // Initialize a price and received time based heap with the head transactions
heads := make(txByPriceAndTime, 0, len(txs)) heads := make(txByPriceAndTime, 0, len(txs))
for from, accTxs := range txs { for from, accTxs := range txs {
@ -110,7 +110,7 @@ func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address]
heap.Init(&heads) heap.Init(&heads)
// Assemble and return the transaction set // Assemble and return the transaction set
return &transactionsByPriceAndNonce{ return &TransactionsByPriceAndNonce{
txs: txs, txs: txs,
heads: heads, heads: heads,
signer: signer, signer: signer,
@ -119,7 +119,7 @@ func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address]
} }
// Peek returns the next transaction by price. // Peek returns the next transaction by price.
func (t *transactionsByPriceAndNonce) Peek() *txpool.LazyTransaction { func (t *TransactionsByPriceAndNonce) Peek() *txpool.LazyTransaction {
if len(t.heads) == 0 { if len(t.heads) == 0 {
return nil return nil
} }
@ -127,7 +127,7 @@ func (t *transactionsByPriceAndNonce) Peek() *txpool.LazyTransaction {
} }
// Shift replaces the current best head with the next one from the same account. // Shift replaces the current best head with the next one from the same account.
func (t *transactionsByPriceAndNonce) Shift() { func (t *TransactionsByPriceAndNonce) Shift() {
acc := t.heads[0].from acc := t.heads[0].from
if txs, ok := t.txs[acc]; ok && len(txs) > 0 { if txs, ok := t.txs[acc]; ok && len(txs) > 0 {
if wrapped, err := newTxWithMinerFee(txs[0], acc, t.baseFee); err == nil { if wrapped, err := newTxWithMinerFee(txs[0], acc, t.baseFee); err == nil {
@ -142,6 +142,6 @@ func (t *transactionsByPriceAndNonce) Shift() {
// Pop removes the best transaction, *not* replacing it with the next one from // Pop removes the best transaction, *not* replacing it with the next one from
// the same account. This should be used when a transaction cannot be executed // the same account. This should be used when a transaction cannot be executed
// and hence all subsequent ones should be discarded from the same account. // and hence all subsequent ones should be discarded from the same account.
func (t *transactionsByPriceAndNonce) Pop() { func (t *TransactionsByPriceAndNonce) Pop() {
heap.Pop(&t.heads) heap.Pop(&t.heads)
} }

View file

@ -97,7 +97,7 @@ func testTransactionPriceNonceSort(t *testing.T, baseFee *big.Int) {
expectedCount += count expectedCount += count
} }
// Sort the transactions and cross check the nonce ordering // Sort the transactions and cross check the nonce ordering
txset := newTransactionsByPriceAndNonce(signer, groups, baseFee) txset := NewTransactionsByPriceAndNonce(signer, groups, baseFee)
txs := types.Transactions{} txs := types.Transactions{}
for tx := txset.Peek(); tx != nil; tx = txset.Peek() { for tx := txset.Peek(); tx != nil; tx = txset.Peek() {
@ -160,7 +160,7 @@ func TestTransactionTimeSort(t *testing.T) {
}) })
} }
// Sort the transactions and cross check the nonce ordering // Sort the transactions and cross check the nonce ordering
txset := newTransactionsByPriceAndNonce(signer, groups, nil) txset := NewTransactionsByPriceAndNonce(signer, groups, nil)
txs := types.Transactions{} txs := types.Transactions{}
for tx := txset.Peek(); tx != nil; tx = txset.Peek() { for tx := txset.Peek(); tx != nil; tx = txset.Peek() {

View file

@ -83,7 +83,7 @@ var (
// information of the sealing block generation. // information of the sealing block generation.
type environment struct { type environment struct {
signer types.Signer signer types.Signer
state *state.StateDB // apply state changes here state state.StateDBI // apply state changes here
tcount int // tx count in cycle tcount int // tx count in cycle
gasPool *core.GasPool // available gas used to pack transactions gasPool *core.GasPool // available gas used to pack transactions
coinbase common.Address coinbase common.Address
@ -131,7 +131,7 @@ func (env *environment) discard() {
// task contains all information for consensus engine sealing and result submitting. // task contains all information for consensus engine sealing and result submitting.
type task struct { type task struct {
receipts []*types.Receipt receipts []*types.Receipt
state *state.StateDB state state.StateDBI
block *types.Block block *types.Block
createdAt time.Time createdAt time.Time
} }
@ -176,7 +176,7 @@ type worker struct {
chainConfig *params.ChainConfig chainConfig *params.ChainConfig
engine consensus.Engine engine consensus.Engine
eth Backend eth Backend
chain *core.BlockChain chain BlockChain
// Feeds // Feeds
pendingLogsFeed event.Feed pendingLogsFeed event.Feed
@ -212,7 +212,7 @@ type worker struct {
snapshotMu sync.RWMutex // The lock used to protect the snapshots below snapshotMu sync.RWMutex // The lock used to protect the snapshots below
snapshotBlock *types.Block snapshotBlock *types.Block
snapshotReceipts types.Receipts snapshotReceipts types.Receipts
snapshotState *state.StateDB snapshotState state.StateDBI
// atomic status counters // atomic status counters
running atomic.Bool // The indicator whether the consensus engine is running or not. running atomic.Bool // The indicator whether the consensus engine is running or not.
@ -246,7 +246,7 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
chainConfig: chainConfig, chainConfig: chainConfig,
engine: engine, engine: engine,
eth: eth, eth: eth,
chain: eth.BlockChain(), chain: eth.MinerChain(),
mux: mux, mux: mux,
isLocalBlock: isLocalBlock, isLocalBlock: isLocalBlock,
coinbase: config.Etherbase, coinbase: config.Etherbase,
@ -266,7 +266,7 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
// Subscribe NewTxsEvent for tx pool // Subscribe NewTxsEvent for tx pool
worker.txsSub = eth.TxPool().SubscribeNewTxsEvent(worker.txsCh) worker.txsSub = eth.TxPool().SubscribeNewTxsEvent(worker.txsCh)
// Subscribe events for blockchain // Subscribe events for blockchain
worker.chainHeadSub = eth.BlockChain().SubscribeChainHeadEvent(worker.chainHeadCh) worker.chainHeadSub = eth.MinerChain().SubscribeChainHeadEvent(worker.chainHeadCh)
// Sanitize recommit interval if the user-specified one is too short. // Sanitize recommit interval if the user-specified one is too short.
recommit := worker.config.Recommit recommit := worker.config.Recommit
@ -337,7 +337,7 @@ func (w *worker) setRecommitInterval(interval time.Duration) {
// pending returns the pending state and corresponding block. The returned // pending returns the pending state and corresponding block. The returned
// values can be nil in case the pending block is not initialized. // values can be nil in case the pending block is not initialized.
func (w *worker) pending() (*types.Block, *state.StateDB) { func (w *worker) pending() (*types.Block, state.StateDBI) {
w.snapshotMu.RLock() w.snapshotMu.RLock()
defer w.snapshotMu.RUnlock() defer w.snapshotMu.RUnlock()
if w.snapshotState == nil { if w.snapshotState == nil {
@ -549,7 +549,7 @@ func (w *worker) mainLoop() {
GasTipCap: tx.GasTipCap(), GasTipCap: tx.GasTipCap(),
}) })
} }
txset := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee) txset := NewTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee)
tcount := w.current.tcount tcount := w.current.tcount
w.commitTransactions(w.current, txset, nil) w.commitTransactions(w.current, txset, nil)
@ -706,7 +706,10 @@ func (w *worker) makeEnv(parent *types.Header, header *types.Header, coinbase co
// the miner to speed block sealing up a bit. // the miner to speed block sealing up a bit.
state, err := w.chain.StateAt(parent.Root) state, err := w.chain.StateAt(parent.Root)
if err != nil { if err != nil {
return nil, err state, err = w.chain.StateAtBlockNumber(parent.Number.Uint64())
if err != nil {
return nil, err
}
} }
state.StartPrefetcher("miner") state.StartPrefetcher("miner")
@ -791,7 +794,7 @@ func (w *worker) applyTransaction(env *environment, tx *types.Transaction) (*typ
return receipt, err return receipt, err
} }
func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAndNonce, interrupt *atomic.Int32) error { func (w *worker) commitTransactions(env *environment, txs *TransactionsByPriceAndNonce, interrupt *atomic.Int32) error {
gasLimit := env.header.GasLimit gasLimit := env.header.GasLimit
if env.gasPool == nil { if env.gasPool == nil {
env.gasPool = new(core.GasPool).AddGas(gasLimit) env.gasPool = new(core.GasPool).AddGas(gasLimit)
@ -987,13 +990,13 @@ func (w *worker) fillTransactions(interrupt *atomic.Int32, env *environment) err
// Fill the block with all available pending transactions. // Fill the block with all available pending transactions.
if len(localTxs) > 0 { if len(localTxs) > 0 {
txs := newTransactionsByPriceAndNonce(env.signer, localTxs, env.header.BaseFee) txs := NewTransactionsByPriceAndNonce(env.signer, localTxs, env.header.BaseFee)
if err := w.commitTransactions(env, txs, interrupt); err != nil { if err := w.commitTransactions(env, txs, interrupt); err != nil {
return err return err
} }
} }
if len(remoteTxs) > 0 { if len(remoteTxs) > 0 {
txs := newTransactionsByPriceAndNonce(env.signer, remoteTxs, env.header.BaseFee) txs := NewTransactionsByPriceAndNonce(env.signer, remoteTxs, env.header.BaseFee)
if err := w.commitTransactions(env, txs, interrupt); err != nil { if err := w.commitTransactions(env, txs, interrupt); err != nil {
return err return err
} }

View file

@ -144,8 +144,9 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
} }
} }
func (b *testWorkerBackend) BlockChain() *core.BlockChain { return b.chain } func (b *testWorkerBackend) BlockChain() BlockChain { return b.chain }
func (b *testWorkerBackend) TxPool() *txpool.TxPool { return b.txPool } func (b *testWorkerBackend) MinerChain() BlockChain { return b.chain }
func (b *testWorkerBackend) TxPool() *txpool.TxPool { return b.txPool }
func (b *testWorkerBackend) newRandomTx(creation bool) *types.Transaction { func (b *testWorkerBackend) newRandomTx(creation bool) *types.Transaction {
var tx *types.Transaction var tx *types.Transaction

View file

@ -65,6 +65,9 @@ type Node struct {
inprocHandler *rpc.Server // In-process RPC request handler to process the API requests inprocHandler *rpc.Server // In-process RPC request handler to process the API requests
databases map[*closeTrackingDB]struct{} // All open databases databases map[*closeTrackingDB]struct{} // All open databases
// for Polaris
disableP2P bool
} }
const ( const (
@ -200,6 +203,11 @@ func (n *Node) Start() error {
return err return err
} }
// SetP2PDisabled sets the P2P disabled flag.
func (n *Node) SetP2PDisabled(disableP2P bool) {
n.disableP2P = disableP2P
}
// Close stops the Node and releases resources acquired in // Close stops the Node and releases resources acquired in
// Node constructor New. // Node constructor New.
func (n *Node) Close() error { func (n *Node) Close() error {
@ -265,9 +273,11 @@ func (n *Node) doClose(errs []error) error {
// openEndpoints starts all network and RPC endpoints. // openEndpoints starts all network and RPC endpoints.
func (n *Node) openEndpoints() error { func (n *Node) openEndpoints() error {
// start networking endpoints // start networking endpoints
n.log.Info("Starting peer-to-peer node", "instance", n.server.Name) if !n.disableP2P {
if err := n.server.Start(); err != nil { n.log.Info("Starting peer-to-peer node", "instance", n.server.Name)
return convertFileLockError(err) if err := n.server.Start(); err != nil {
return convertFileLockError(err)
}
} }
// start RPC endpoints // start RPC endpoints
err := n.startRPC() err := n.startRPC()

View file

@ -128,7 +128,7 @@ const (
DefaultElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have. DefaultElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have.
InitialBaseFee = 1000000000 // Initial base fee for EIP-1559 blocks. InitialBaseFee = 1000000000 // Initial base fee for EIP-1559 blocks.
MaxCodeSize = 24576 // Maximum bytecode to permit for a contract MaxCodeSize = 40000 // Maximum bytecode to permit for a contract
MaxInitCodeSize = 2 * MaxCodeSize // Maximum initcode to permit in a creation transaction and create instructions MaxInitCodeSize = 2 * MaxCodeSize // Maximum initcode to permit in a creation transaction and create instructions
// Precompiled contract gas prices // Precompiled contract gas prices

View file

@ -33,7 +33,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/ethereum/go-ethereum/signer/core/apitypes"

View file

@ -31,7 +31,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/signer/core" "github.com/ethereum/go-ethereum/signer/core"
"github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/ethereum/go-ethereum/signer/core/apitypes"

View file

@ -22,7 +22,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/ethereum/go-ethereum/signer/core/apitypes"
) )

View file

@ -27,7 +27,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/console/prompt" "github.com/ethereum/go-ethereum/console/prompt"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )

View file

@ -19,7 +19,7 @@ package core
import ( import (
"context" "context"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
) )

View file

@ -24,7 +24,7 @@ import (
"strings" "strings"
"github.com/dop251/goja" "github.com/dop251/goja"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/internal/jsre/deps" "github.com/ethereum/go-ethereum/internal/jsre/deps"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/signer/core" "github.com/ethereum/go-ethereum/signer/core"

View file

@ -26,7 +26,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/ethapi"
"github.com/ethereum/go-ethereum/signer/core" "github.com/ethereum/go-ethereum/signer/core"
"github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/ethereum/go-ethereum/signer/core/apitypes"
"github.com/ethereum/go-ethereum/signer/storage" "github.com/ethereum/go-ethereum/signer/storage"

View file

@ -314,7 +314,7 @@ func validateHeader(h *btHeader, h2 *types.Header) error {
return nil return nil
} }
func (t *BlockTest) validatePostState(statedb *state.StateDB) error { func (t *BlockTest) validatePostState(statedb state.StateDBI) error {
// validate post state accounts in test file against what we have in state db // validate post state accounts in test file against what we have in state db
for addr, acct := range t.json.Post { for addr, acct := range t.json.Post {
// address is indirectly verified by the other fields, as it's the db key // address is indirectly verified by the other fields, as it's the db key

View file

@ -18,6 +18,7 @@ package bls
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -92,7 +93,7 @@ func fuzz(id byte, data []byte) int {
} }
cpy := make([]byte, len(data)) cpy := make([]byte, len(data))
copy(cpy, data) copy(cpy, data)
_, err := precompile.Run(cpy) _, err := precompile.Run(context.Background(), nil, cpy, common.Address{}, nil)
if !bytes.Equal(cpy, data) { if !bytes.Equal(cpy, data) {
panic(fmt.Sprintf("input data modified, precompile %d: %x %x", id, data, cpy)) panic(fmt.Sprintf("input data modified, precompile %d: %x %x", id, data, cpy))
} }

View file

@ -83,7 +83,7 @@ func TestState(t *testing.T) {
t.Run(key+"/hash/trie", func(t *testing.T) { t.Run(key+"/hash/trie", func(t *testing.T) {
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error { withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
var result error var result error
test.Run(subtest, vmconfig, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) { test.Run(subtest, vmconfig, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state state.StateDBI) {
result = st.checkFailure(t, err) result = st.checkFailure(t, err)
}) })
return result return result
@ -92,7 +92,7 @@ func TestState(t *testing.T) {
t.Run(key+"/hash/snap", func(t *testing.T) { t.Run(key+"/hash/snap", func(t *testing.T) {
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error { withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
var result error var result error
test.Run(subtest, vmconfig, true, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) { test.Run(subtest, vmconfig, true, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state state.StateDBI) {
if snaps != nil && state != nil { if snaps != nil && state != nil {
if _, err := snaps.Journal(state.IntermediateRoot(false)); err != nil { if _, err := snaps.Journal(state.IntermediateRoot(false)); err != nil {
result = err result = err
@ -107,7 +107,7 @@ func TestState(t *testing.T) {
t.Run(key+"/path/trie", func(t *testing.T) { t.Run(key+"/path/trie", func(t *testing.T) {
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error { withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
var result error var result error
test.Run(subtest, vmconfig, false, rawdb.PathScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) { test.Run(subtest, vmconfig, false, rawdb.PathScheme, func(err error, snaps *snapshot.Tree, state state.StateDBI) {
result = st.checkFailure(t, err) result = st.checkFailure(t, err)
}) })
return result return result
@ -116,7 +116,7 @@ func TestState(t *testing.T) {
t.Run(key+"/path/snap", func(t *testing.T) { t.Run(key+"/path/snap", func(t *testing.T) {
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error { withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
var result error var result error
test.Run(subtest, vmconfig, true, rawdb.PathScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) { test.Run(subtest, vmconfig, true, rawdb.PathScheme, func(err error, snaps *snapshot.Tree, state state.StateDBI) {
if snaps != nil && state != nil { if snaps != nil && state != nil {
if _, err := snaps.Journal(state.IntermediateRoot(false)); err != nil { if _, err := snaps.Journal(state.IntermediateRoot(false)); err != nil {
result = err result = err
@ -276,7 +276,7 @@ func runBenchmark(b *testing.B, t *StateTest) {
b.ResetTimer() b.ResetTimer()
for n := 0; n < b.N; n++ { for n := 0; n < b.N; n++ {
snapshot := statedb.Snapshot() snapshot := statedb.Snapshot()
statedb.Prepare(rules, msg.From, context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList) statedb.Prepare(rules, msg.From, context.Coinbase, msg.To, evm.PrecompileManager.GetActive(&rules), msg.AccessList)
b.StartTimer() b.StartTimer()
start := time.Now() start := time.Now()

View file

@ -190,7 +190,7 @@ func (t *StateTest) checkError(subtest StateSubtest, err error) error {
} }
// Run executes a specific subtest and verifies the post-state and logs // Run executes a specific subtest and verifies the post-state and logs
func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string, postCheck func(err error, snaps *snapshot.Tree, state *state.StateDB)) (result error) { func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string, postCheck func(err error, snaps *snapshot.Tree, state state.StateDBI)) (result error) {
triedb, snaps, statedb, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme) triedb, snaps, statedb, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme)
// Invoke the callback at the end of function for further analysis. // Invoke the callback at the end of function for further analysis.
@ -225,7 +225,7 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bo
} }
// RunNoVerify runs a specific subtest and returns the statedb and post-state root // RunNoVerify runs a specific subtest and returns the statedb and post-state root
func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (*trie.Database, *snapshot.Tree, *state.StateDB, common.Hash, error) { func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (*trie.Database, *snapshot.Tree, state.StateDBI, common.Hash, error) {
config, eips, err := GetChainConfig(subtest.Fork) config, eips, err := GetChainConfig(subtest.Fork)
if err != nil { if err != nil {
return nil, nil, nil, common.Hash{}, UnsupportedForkError{subtest.Fork} return nil, nil, nil, common.Hash{}, UnsupportedForkError{subtest.Fork}
@ -306,7 +306,7 @@ func (t *StateTest) gasLimit(subtest StateSubtest) uint64 {
return t.json.Tx.GasLimit[t.json.Post[subtest.Fork][subtest.Index].Indexes.Gas] return t.json.Tx.GasLimit[t.json.Post[subtest.Fork][subtest.Index].Indexes.Gas]
} }
func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter bool, scheme string) (*trie.Database, *snapshot.Tree, *state.StateDB) { func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter bool, scheme string) (*trie.Database, *snapshot.Tree, state.StateDBI) {
tconf := &trie.Config{Preimages: true} tconf := &trie.Config{Preimages: true}
if scheme == rawdb.HashScheme { if scheme == rawdb.HashScheme {
tconf.HashDB = hashdb.Defaults tconf.HashDB = hashdb.Defaults