From 16a8208f36af2c96e189cd8bd8604e672cea86fa Mon Sep 17 00:00:00 2001 From: codchen Date: Fri, 20 Oct 2023 13:03:53 +0800 Subject: [PATCH] use interface instead of concrete state type --- accounts/abi/bind/backends/simulated.go | 10 +- consensus/beacon/consensus.go | 6 +- consensus/clique/clique.go | 6 +- consensus/consensus.go | 6 +- consensus/ethash/consensus.go | 8 +- consensus/misc/dao.go | 4 +- core/blockchain.go | 6 +- core/blockchain_reader.go | 4 +- core/state_processor.go | 9 +- core/txpool/blobpool/blobpool.go | 8 +- core/txpool/blobpool/blobpool_test.go | 5 +- core/txpool/blobpool/interface.go | 4 +- core/txpool/legacypool/legacypool.go | 6 +- core/txpool/legacypool/legacypool_test.go | 7 +- core/txpool/legacypool/noncer.go | 6 +- core/txpool/validation.go | 4 +- core/types.go | 2 +- core/vm/interface.go | 15 + eth/api_backend.go | 11 +- eth/api_debug.go | 11 +- eth/state_accessor.go | 10 +- eth/tracers/api.go | 12 +- eth/tracers/api_test.go | 5 +- graphql/graphql.go | 4 +- internal/ethapi/api.go | 22 +- internal/ethapi/api_test.go | 8 +- internal/ethapi/backend.go | 7 +- internal/ethapi/transaction_args_test.go | 9 +- les/api_backend.go | 336 ++++++++++++++++++++++ miner/miner.go | 4 +- miner/miner_test.go | 4 +- miner/worker.go | 18 +- tests/block_test_util.go | 3 +- 33 files changed, 473 insertions(+), 107 deletions(-) create mode 100644 les/api_backend.go diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 2faf274dbd..3fb6698dd3 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -180,7 +180,7 @@ func (b *SimulatedBackend) Fork(ctx context.Context, parent common.Hash) error { } // 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) (vm.StateDB, error) { if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number) == 0 { return b.blockchain.State() } @@ -640,7 +640,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs // callContract implements common code between normal and pending contract calls. // 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 vm.StateDB) (*core.ExecutionResult, error) { // Gas prices post 1559 need to be initialized if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) { return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") @@ -680,7 +680,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM } // Set infinite balance to the fake caller account. - from := stateDB.GetOrNewStateObject(call.From) + from := stateDB.(*state.StateDB).GetOrNewStateObject(call.From) from.SetBalance(math.MaxBig256) // Execute the call. @@ -739,7 +739,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa return err } b.pendingBlock = blocks[0] - b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil) + b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.(*state.StateDB).Database(), nil) b.pendingReceipts = receipts[0] return nil } @@ -862,7 +862,7 @@ func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error { return err } b.pendingBlock = blocks[0] - b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil) + b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.(*state.StateDB).Database(), nil) return nil } diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index e856f4e6ce..7e5d06e03b 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -25,8 +25,8 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/consensus/misc/eip4844" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" @@ -347,7 +347,7 @@ func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.H } // 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 vm.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { if !beacon.IsPoSHeader(header) { beacon.ethone.Finalize(chain, header, state, txs, uncles, nil) return @@ -364,7 +364,7 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types. // FinalizeAndAssemble implements consensus.Engine, setting the final state and // 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 vm.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { if !beacon.IsPoSHeader(header) { return beacon.ethone.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts, nil) } diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index c693189ea5..537d42a418 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -34,8 +34,8 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" @@ -580,13 +580,13 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header // Finalize implements consensus.Engine. There is no post-transaction // 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 vm.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { // No block rewards in PoA, so the state remains as is } // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, // 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 vm.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { if len(withdrawals) > 0 { return nil, errors.New("clique does not support withdrawals") } diff --git a/consensus/consensus.go b/consensus/consensus.go index 3a2c2d2229..63adb5fc85 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -21,8 +21,8 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" ) @@ -88,7 +88,7 @@ type Engine interface { // // Note: The state database might be updated to reflect any consensus rules // 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 vm.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) // 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 // 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 vm.StateDB, txs []*types.Transaction, 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 diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 130dfdf213..2eb85238a2 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -28,8 +28,8 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" @@ -500,14 +500,14 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H } // 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 vm.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { // Accumulate any block and uncle rewards accumulateRewards(chain.Config(), state, header, uncles) } // FinalizeAndAssemble implements consensus.Engine, accumulating the block and // 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 vm.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { if len(withdrawals) > 0 { return nil, errors.New("ethash does not support withdrawals") } @@ -569,7 +569,7 @@ var ( // AccumulateRewards credits the coinbase of the given block with the mining // reward. The total reward consists of the static block reward and rewards for // 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 vm.StateDB, header *types.Header, uncles []*types.Header) { // Select the correct block reward based on chain progression blockReward := FrontierBlockReward if config.IsByzantium(header.Number) { diff --git a/consensus/misc/dao.go b/consensus/misc/dao.go index 96995616de..b4cfdd509f 100644 --- a/consensus/misc/dao.go +++ b/consensus/misc/dao.go @@ -21,8 +21,8 @@ import ( "errors" "math/big" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" ) @@ -72,7 +72,7 @@ func VerifyDAOHeaderExtraData(config *params.ChainConfig, header *types.Header) // 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 // contract. -func ApplyDAOHardFork(statedb *state.StateDB) { +func ApplyDAOHardFork(statedb vm.StateDB) { // Retrieve the contract to refund balances into if !statedb.Exist(params.DAORefundContract) { statedb.CreateAccount(params.DAORefundContract) diff --git a/core/blockchain.go b/core/blockchain.go index f458da8257..2c572bc9c9 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1385,7 +1385,7 @@ func (bc *BlockChain) writeKnownBlock(block *types.Block) error { // writeBlockWithState writes block, metadata and corresponding state data to the // 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 vm.StateDB) error { // Calculate the total difficulty of the block ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1) 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, // 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 vm.StateDB, emitHeadEvent bool) (status WriteStatus, err error) { if !bc.chainmu.TryLock() { return NonStatTy, errChainStopped } @@ -1484,7 +1484,7 @@ func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types // writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead. // 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 vm.StateDB, emitHeadEvent bool) (status WriteStatus, err error) { if err := bc.writeBlockWithState(block, receipts, state); err != nil { return NonStatTy, err } diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index 466a86c144..10ce7f5982 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -320,12 +320,12 @@ func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) ([]byte, error) { } // State returns a new mutable state based on the current HEAD block. -func (bc *BlockChain) State() (*state.StateDB, error) { +func (bc *BlockChain) State() (vm.StateDB, error) { return bc.StateAt(bc.CurrentBlock().Root) } // 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) (vm.StateDB, error) { return state.New(root, bc.stateCache, bc.snaps) } diff --git a/core/state_processor.go b/core/state_processor.go index 9a4333f723..15f0223287 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -24,7 +24,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" @@ -57,7 +56,7 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consen // 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 // 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 vm.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) { var ( receipts types.Receipts usedGas = new(uint64) @@ -104,7 +103,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg 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 vm.StateDB, 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. txContext := NewEVMTxContext(msg) evm.Reset(txContext, statedb) @@ -158,7 +157,7 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta // and uses the input parameters for its environment. It returns the receipt // for the transaction, gas used and an error if the transaction failed, // 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 vm.StateDB, 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) if err != nil { return nil, err @@ -172,7 +171,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo // ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root // 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 vm.StateDB) { // If EIP-4788 is enabled, we need to invoke the beaconroot storage contract with // the new root msg := &Message{ diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go index 32c6c0e8fe..e2ec955b2c 100644 --- a/core/txpool/blobpool/blobpool.go +++ b/core/txpool/blobpool/blobpool.go @@ -33,9 +33,9 @@ import ( "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" @@ -302,9 +302,9 @@ type BlobPool struct { signer types.Signer // Transaction signer to use for sender recovery chain BlockChain // Chain object to access the state through - head *types.Header // Current head of the chain - state *state.StateDB // Current state at the head of the chain - gasTip *uint256.Int // Currently accepted minimum gas tip + head *types.Header // Current head of the chain + state vm.StateDB // Current state at the head of the chain + gasTip *uint256.Int // Currently accepted minimum gas tip lookup map[common.Hash]uint64 // Lookup table mapping hashes to tx billy entries index map[common.Address][]*blobTxMeta // Blob transactions grouped by accounts, sorted by nonce diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go index fa3e8edc90..bc170594a8 100644 --- a/core/txpool/blobpool/blobpool_test.go +++ b/core/txpool/blobpool/blobpool_test.go @@ -37,6 +37,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/ethdb/memorydb" @@ -84,7 +85,7 @@ type testBlockChain struct { config *params.ChainConfig basefee *uint256.Int blobfee *uint256.Int - statedb *state.StateDB + statedb vm.StateDB } func (bc *testBlockChain) Config() *params.ChainConfig { @@ -158,7 +159,7 @@ func (bt *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block return nil } -func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { +func (bc *testBlockChain) StateAt(common.Hash) (vm.StateDB, error) { return bc.statedb, nil } diff --git a/core/txpool/blobpool/interface.go b/core/txpool/blobpool/interface.go index 6f296a54bd..cad44f4db8 100644 --- a/core/txpool/blobpool/interface.go +++ b/core/txpool/blobpool/interface.go @@ -18,8 +18,8 @@ package blobpool import ( "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" ) @@ -40,5 +40,5 @@ type BlockChain interface { GetBlock(hash common.Hash, number uint64) *types.Block // StateAt returns a state database for a given root hash (generally the head). - StateAt(root common.Hash) (*state.StateDB, error) + StateAt(root common.Hash) (vm.StateDB, error) } diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index 8450d89a2c..bd5683c5bd 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -30,9 +30,9 @@ import ( "github.com/ethereum/go-ethereum/common/prque" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" @@ -115,7 +115,7 @@ type BlockChain interface { GetBlock(hash common.Hash, number uint64) *types.Block // StateAt returns a state database for a given root hash (generally the head). - StateAt(root common.Hash) (*state.StateDB, error) + StateAt(root common.Hash) (vm.StateDB, error) } // Config are the configuration parameters of the transaction pool. @@ -208,7 +208,7 @@ type LegacyPool struct { mu sync.RWMutex currentHead atomic.Pointer[types.Header] // Current head of the blockchain - currentState *state.StateDB // Current state in the blockchain head + currentState vm.StateDB // Current state in the blockchain head pendingNonces *noncer // Pending state tracking virtual nonces locals *accountSet // Set of local transaction to exempt from eviction rules diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index 0366a58d61..ab24edb6ea 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -35,6 +35,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/params" @@ -63,7 +64,7 @@ func init() { type testBlockChain struct { config *params.ChainConfig gasLimit atomic.Uint64 - statedb *state.StateDB + statedb vm.StateDB chainHeadFeed *event.Feed } @@ -88,7 +89,7 @@ func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block 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) (vm.StateDB, error) { return bc.statedb, nil } @@ -246,7 +247,7 @@ type testChain struct { // testChain.State() is used multiple times to reset the pending state. // when simulate is true it will create a state that indicates // that tx0 and tx1 are included in the chain. -func (c *testChain) State() (*state.StateDB, error) { +func (c *testChain) State() (vm.StateDB, error) { // delay "state change" by one. The tx pool fetches the // state multiple times and by delaying it a bit we simulate // a state change between those fetches. diff --git a/core/txpool/legacypool/noncer.go b/core/txpool/legacypool/noncer.go index 2c65dd2cae..9d2ecf9ab6 100644 --- a/core/txpool/legacypool/noncer.go +++ b/core/txpool/legacypool/noncer.go @@ -20,20 +20,20 @@ import ( "sync" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/vm" ) // noncer is a tiny virtual state database to manage the executable nonces of // accounts in the pool, falling back to reading from a real state database if // an account is unknown. type noncer struct { - fallback *state.StateDB + fallback vm.StateDB nonces map[common.Address]uint64 lock sync.Mutex } // newNoncer creates a new virtual state database to track the pool nonces. -func newNoncer(statedb *state.StateDB) *noncer { +func newNoncer(statedb vm.StateDB) *noncer { return &noncer{ fallback: statedb.Copy(), nonces: make(map[common.Address]uint64), diff --git a/core/txpool/validation.go b/core/txpool/validation.go index 0df363d81d..54f3966226 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -23,8 +23,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -169,7 +169,7 @@ func validateBlobSidecar(hashes []common.Hash, sidecar *types.BlobTxSidecar) err // ValidationOptionsWithState define certain differences between stateful transaction // validation across the different pools without having to duplicate those checks. type ValidationOptionsWithState struct { - State *state.StateDB // State database to check nonces and balances against + State vm.StateDB // State database to check nonces and balances against // 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 diff --git a/core/types.go b/core/types.go index 36eb0d1ded..e8ed2a098c 100644 --- a/core/types.go +++ b/core/types.go @@ -49,5 +49,5 @@ type Processor interface { // 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 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 vm.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) } diff --git a/core/vm/interface.go b/core/vm/interface.go index 26814d3d2f..4f1424076f 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -20,6 +20,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" ) @@ -78,6 +79,20 @@ type StateDB interface { AddLog(*types.Log) AddPreimage(common.Hash, []byte) + + // new methods + Error() error + GetStorageRoot(common.Address) common.Hash + SetBalance(common.Address, *big.Int) + SetStorage(common.Address, map[common.Hash]common.Hash) + Finalise(deleteEmptyObjects bool) + Commit(block uint64, deleteEmptyObjects bool) (common.Hash, error) + SetTxContext(thash common.Hash, ti int) + Copy() *state.StateDB + IntermediateRoot(deleteEmptyObjects bool) common.Hash + GetLogs(hash common.Hash, blockNumber uint64, blockHash common.Hash) []*types.Log + TxIndex() int + Preimages() map[common.Hash][]byte } // CallContext provides a basic interface for the EVM calling conventions. The EVM diff --git a/eth/api_backend.go b/eth/api_backend.go index 84eb200095..1fbd2f65a0 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -29,7 +29,6 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -186,7 +185,7 @@ func (b *EthAPIBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) 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) (vm.StateDB, *types.Header, error) { // Pending state is only known by the miner if number == rpc.PendingBlockNumber { block, state := b.eth.miner.Pending() @@ -210,7 +209,7 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B 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) (vm.StateDB, *types.Header, error) { if blockNr, ok := blockNrOrHash.Number(); ok { return b.StateAndHeaderByNumber(ctx, blockNr) } @@ -249,7 +248,7 @@ func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { 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 (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state vm.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM { if vmConfig == nil { vmConfig = b.eth.blockchain.GetVMConfig() } @@ -408,10 +407,10 @@ func (b *EthAPIBackend) StartMining() error { 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 vm.StateDB, readOnly bool, preferDisk bool) (vm.StateDB, tracers.StateReleaseFunc, error) { 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, vm.StateDB, tracers.StateReleaseFunc, error) { return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) } diff --git a/eth/api_debug.go b/eth/api_debug.go index 05010a3969..dfb8182879 100644 --- a/eth/api_debug.go +++ b/eth/api_debug.go @@ -27,6 +27,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/log" @@ -60,7 +61,7 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) { if stateDb == nil { return state.Dump{}, errors.New("pending state is not available") } - return stateDb.RawDump(opts), nil + return stateDb.(*state.StateDB).RawDump(opts), nil } var header *types.Header switch blockNr { @@ -84,7 +85,7 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) { if err != nil { return state.Dump{}, err } - return stateDb.RawDump(opts), nil + return stateDb.(*state.StateDB).RawDump(opts), nil } // Preimage is a debug API function that returns the preimage for a sha3 hash, if known. @@ -134,7 +135,7 @@ const AccountRangeMaxResults = 256 // 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.Dump, error) { - var stateDb *state.StateDB + var stateDb vm.StateDB var err error if number, ok := blockNrOrHash.Number(); ok { @@ -229,13 +230,13 @@ func (api *DebugAPI) StorageRangeAt(ctx context.Context, blockNrOrHash rpc.Block 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 vm.StateDB, root common.Hash, address common.Address, start []byte, maxResult int) (StorageRangeResult, error) { storageRoot := statedb.GetStorageRoot(address) if storageRoot == types.EmptyRootHash || storageRoot == (common.Hash{}) { return StorageRangeResult{}, nil // empty storage } id := trie.StorageTrieID(root, crypto.Keccak256Hash(address.Bytes()), storageRoot) - tr, err := trie.NewStateTrie(id, statedb.Database().TrieDB()) + tr, err := trie.NewStateTrie(id, statedb.(*state.StateDB).Database().TrieDB()) if err != nil { return StorageRangeResult{}, err } diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 24694df66c..ab9612f0e6 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -37,7 +37,7 @@ import ( // for releasing state. 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 vm.StateDB, readOnly bool, preferDisk bool) (statedb vm.StateDB, release tracers.StateReleaseFunc, err error) { var ( current *types.Block database state.Database @@ -74,7 +74,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u } } // The optional base statedb is given, mark the start point as parent block - statedb, database, triedb, report = base, base.Database(), base.Database().TrieDB(), false + statedb, database, triedb, report = base, base.(*state.StateDB).Database(), base.(*state.StateDB).Database().TrieDB(), false current = eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1) } else { // Otherwise, try to reexec blocks until we find a state or reach our limit @@ -174,7 +174,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u 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) (vm.StateDB, func(), error) { // Check if the requested state is available in the live chain. statedb, err := eth.blockchain.StateAt(block.Root()) 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 // provided, it would be preferable to start from a fresh state, if we have it // 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 vm.StateDB, readOnly bool, preferDisk bool) (statedb vm.StateDB, release tracers.StateReleaseFunc, err error) { if eth.blockchain.TrieDB().Scheme() == rawdb.HashScheme { 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. -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, vm.StateDB, tracers.StateReleaseFunc, error) { // Short circuit if it's genesis block. if block.NumberU64() == 0 { return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis") diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 7c0028601d..867c112546 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -85,8 +85,8 @@ type Backend interface { ChainConfig() *params.ChainConfig Engine() consensus.Engine ChainDb() ethdb.Database - StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error) - StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) + StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base vm.StateDB, readOnly bool, preferDisk bool) (vm.StateDB, StateReleaseFunc, error) + StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, vm.StateDB, StateReleaseFunc, error) } // API is the collection of tracing APIs exposed over the private debugging endpoint. @@ -309,7 +309,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed number uint64 traced uint64 failed error - statedb *state.StateDB + statedb vm.StateDB release StateReleaseFunc ) // Ensure everything is properly cleaned up on any exit path @@ -369,7 +369,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed // if the relevant state is available in disk. var preferDisk bool if statedb != nil { - s1, s2, s3 := statedb.Database().TrieDB().Size() + s1, s2, s3 := statedb.(*state.StateDB).Database().TrieDB().Size() preferDisk = s1+s2+s3 > defaultTracechainMemLimit } statedb, release, err = api.backend.StateAtBlock(ctx, block, reexec, statedb, false, preferDisk) @@ -627,7 +627,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 // runs along and executes txes without tracing enabled to generate their prestate. // 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 vm.StateDB, config *TraceConfig) ([]*txTraceResult, error) { // Execute all the transaction contained within the block concurrently var ( txs = block.Transactions() @@ -934,7 +934,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc // traceTx configures a new tracer according to the provided configuration, and // executes the given message in the provided environment. The return value will // 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 vm.StateDB, config *TraceConfig) (interface{}, error) { var ( tracer Tracer err error diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index 49c3ebb67d..c5566cd819 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -34,7 +34,6 @@ import ( "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" @@ -139,7 +138,7 @@ func (b *testBackend) teardown() { 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 vm.StateDB, readOnly bool, preferDisk bool) (vm.StateDB, StateReleaseFunc, error) { statedb, err := b.chain.StateAt(block.Root()) if err != nil { return nil, nil, errStateNotFound @@ -155,7 +154,7 @@ func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reex 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, vm.StateDB, StateReleaseFunc, error) { parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1) if parent == nil { return nil, vm.BlockContext{}, nil, nil, errBlockNotFound diff --git a/graphql/graphql.go b/graphql/graphql.go index 49be23af69..96627db0cb 100644 --- a/graphql/graphql.go +++ b/graphql/graphql.go @@ -32,8 +32,8 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/rlp" @@ -86,7 +86,7 @@ type Account struct { } // 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) (vm.StateDB, error) { state, _, err := a.r.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash) return state, err } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index c0b28e4b69..a2593fdfd4 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -950,7 +950,7 @@ type OverrideAccount struct { type StateOverride map[common.Address]OverrideAccount // Apply overrides the fields of specified accounts into the given state. -func (diff *StateOverride) Apply(state *state.StateDB) error { +func (diff *StateOverride) Apply(state vm.StateDB) error { if diff == nil { return nil } @@ -1063,7 +1063,7 @@ func (context *ChainContext) GetHeader(hash common.Hash, number uint64) *types.H 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 vm.StateDB, header *types.Header, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) { if err := overrides.Apply(state); err != nil { return nil, err } @@ -1178,6 +1178,24 @@ func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrO return result.Return(), result.Err } +<<<<<<< HEAD +======= +// 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 +// error means execution failed due to reasons unrelated to the gas limit. +func executeEstimate(ctx context.Context, b Backend, args TransactionArgs, state vm.StateDB, header *types.Header, gasCap uint64, gasLimit uint64) (bool, *core.ExecutionResult, error) { + args.Gas = (*hexutil.Uint64)(&gasLimit) + result, err := doCall(ctx, b, args, state, header, nil, nil, 0, gasCap) + if err != nil { + if errors.Is(err, core.ErrIntrinsicGas) { + return true, nil, nil // Special case, raise gas limit + } + return true, nil, err // Bail out + } + return result.Failed(), result, nil +} + +>>>>>>> 6c86d947d (use interface instead of concrete state type) // DoEstimateGas returns the lowest possible gas limit that allows the transaction to run // successfully at block `blockNrOrHash`. It returns error if the transaction would revert, or if // there are unexpected failures. The gas limit is capped by both `args.Gas` (if non-nil & diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index c2490ac703..d6ec028be2 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -39,7 +39,6 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" @@ -501,7 +500,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) { 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) (vm.StateDB, *types.Header, error) { if number == rpc.PendingBlockNumber { panic("pending state not implemented") } @@ -515,7 +514,7 @@ func (b testBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.Bloc stateDb, err := b.chain.StateAt(header.Root) 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) (vm.StateDB, *types.Header, error) { if blockNr, ok := blockNrOrHash.Number(); ok { return b.StateAndHeaderByNumber(ctx, blockNr) } @@ -536,7 +535,8 @@ func (b testBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { } 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 (b testBackend) GetEVM(ctx context.Context, msg *core.Message, state vm.StateDB, header *types.Header, vmConfig *vm.Config, blockContext *vm.BlockContext) *vm.EVM { + vmError := func() error { return nil } if vmConfig == nil { vmConfig = b.chain.GetVMConfig() } diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 50f338f5ca..fc3ba3f85c 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -28,7 +28,6 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" @@ -63,12 +62,12 @@ type Backend interface { BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) BlockByHash(ctx context.Context, hash common.Hash) (*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) - StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) + StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.StateDB, *types.Header, error) + StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.StateDB, *types.Header, error) PendingBlockAndReceipts() (*types.Block, types.Receipts) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) 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 + GetEVM(ctx context.Context, msg *core.Message, state vm.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go index 9dc58bdeb5..e4cf3abdd9 100644 --- a/internal/ethapi/transaction_args_test.go +++ b/internal/ethapi/transaction_args_test.go @@ -31,7 +31,6 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" @@ -291,10 +290,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) { 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) (vm.StateDB, *types.Header, error) { 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) (vm.StateDB, *types.Header, error) { return nil, nil, nil } func (b *backendMock) PendingBlockAndReceipts() (*types.Block, types.Receipts) { return nil, nil } @@ -305,8 +304,8 @@ func (b *backendMock) GetLogs(ctx context.Context, blockHash common.Hash, number return nil, 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 { - return nil +func (b *backendMock) GetEVM(ctx context.Context, msg *core.Message, state vm.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM { + return nil, nil } func (b *backendMock) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { return nil } func (b *backendMock) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { diff --git a/les/api_backend.go b/les/api_backend.go new file mode 100644 index 0000000000..dd869628bf --- /dev/null +++ b/les/api_backend.go @@ -0,0 +1,336 @@ +// Copyright 2016 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 . + +package les + +import ( + "context" + "errors" + "math/big" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/bloombits" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/gasprice" + "github.com/ethereum/go-ethereum/eth/tracers" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/light" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" +) + +type LesApiBackend struct { + extRPCEnabled bool + allowUnprotectedTxs bool + eth *LightEthereum + gpo *gasprice.Oracle +} + +func (b *LesApiBackend) ChainConfig() *params.ChainConfig { + return b.eth.chainConfig +} + +func (b *LesApiBackend) CurrentBlock() *types.Header { + return b.eth.BlockChain().CurrentHeader() +} + +func (b *LesApiBackend) SetHead(number uint64) { + b.eth.blockchain.SetHead(number) +} + +func (b *LesApiBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { + // Return the latest current as the pending one since there + // is no pending notion in the light client. TODO(rjl493456442) + // unify the behavior of `HeaderByNumber` and `PendingBlockAndReceipts`. + if number == rpc.PendingBlockNumber { + return b.eth.blockchain.CurrentHeader(), nil + } + if number == rpc.LatestBlockNumber { + return b.eth.blockchain.CurrentHeader(), nil + } + return b.eth.blockchain.GetHeaderByNumberOdr(ctx, uint64(number)) +} + +func (b *LesApiBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) { + if blockNr, ok := blockNrOrHash.Number(); ok { + return b.HeaderByNumber(ctx, blockNr) + } + if hash, ok := blockNrOrHash.Hash(); ok { + header, err := b.HeaderByHash(ctx, hash) + if err != nil { + return nil, err + } + if header == nil { + return nil, errors.New("header for hash not found") + } + if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { + return nil, errors.New("hash is not currently canonical") + } + return header, nil + } + return nil, errors.New("invalid arguments; neither block nor hash specified") +} + +func (b *LesApiBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { + return b.eth.blockchain.GetHeaderByHash(hash), nil +} + +func (b *LesApiBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { + header, err := b.HeaderByNumber(ctx, number) + if header == nil || err != nil { + return nil, err + } + return b.BlockByHash(ctx, header.Hash()) +} + +func (b *LesApiBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + return b.eth.blockchain.GetBlockByHash(ctx, hash) +} + +func (b *LesApiBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { + if blockNr, ok := blockNrOrHash.Number(); ok { + return b.BlockByNumber(ctx, blockNr) + } + if hash, ok := blockNrOrHash.Hash(); ok { + block, err := b.BlockByHash(ctx, hash) + if err != nil { + return nil, err + } + if block == nil { + return nil, errors.New("header found, but block body is missing") + } + if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(block.NumberU64()) != hash { + return nil, errors.New("hash is not currently canonical") + } + return block, nil + } + return nil, errors.New("invalid arguments; neither block nor hash specified") +} + +func (b *LesApiBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { + return light.GetBody(ctx, b.eth.odr, hash, uint64(number)) +} + +func (b *LesApiBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) { + return nil, nil +} + +func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.StateDB, *types.Header, error) { + header, err := b.HeaderByNumber(ctx, number) + if err != nil { + return nil, nil, err + } + if header == nil { + return nil, nil, errors.New("header not found") + } + return light.NewState(ctx, header, b.eth.odr), header, nil +} + +func (b *LesApiBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.StateDB, *types.Header, error) { + if blockNr, ok := blockNrOrHash.Number(); ok { + return b.StateAndHeaderByNumber(ctx, blockNr) + } + if hash, ok := blockNrOrHash.Hash(); ok { + header := b.eth.blockchain.GetHeaderByHash(hash) + if header == nil { + return nil, nil, errors.New("header for hash not found") + } + if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { + return nil, nil, errors.New("hash is not currently canonical") + } + return light.NewState(ctx, header, b.eth.odr), header, nil + } + return nil, nil, errors.New("invalid arguments; neither block nor hash specified") +} + +func (b *LesApiBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { + if number := rawdb.ReadHeaderNumber(b.eth.chainDb, hash); number != nil { + return light.GetBlockReceipts(ctx, b.eth.odr, hash, *number) + } + return nil, nil +} + +func (b *LesApiBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) { + return light.GetBlockLogs(ctx, b.eth.odr, hash, number) +} + +func (b *LesApiBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { + if number := rawdb.ReadHeaderNumber(b.eth.chainDb, hash); number != nil { + return b.eth.blockchain.GetTdOdr(ctx, hash, *number) + } + return nil +} + +func (b *LesApiBackend) GetEVM(ctx context.Context, msg *core.Message, state vm.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, func() error) { + if vmConfig == nil { + vmConfig = new(vm.Config) + } + txContext := core.NewEVMTxContext(msg) + context := core.NewEVMBlockContext(header, b.eth.blockchain, nil) + if blockCtx != nil { + context = *blockCtx + } + return vm.NewEVM(context, txContext, state, b.eth.chainConfig, *vmConfig), state.Error +} + +func (b *LesApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { + return b.eth.txPool.Add(ctx, signedTx) +} + +func (b *LesApiBackend) RemoveTx(txHash common.Hash) { + b.eth.txPool.RemoveTx(txHash) +} + +func (b *LesApiBackend) GetPoolTransactions() (types.Transactions, error) { + return b.eth.txPool.GetTransactions() +} + +func (b *LesApiBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction { + return b.eth.txPool.GetTransaction(txHash) +} + +func (b *LesApiBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { + return light.GetTransaction(ctx, b.eth.odr, txHash) +} + +func (b *LesApiBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) { + return b.eth.txPool.GetNonce(ctx, addr) +} + +func (b *LesApiBackend) Stats() (pending int, queued int) { + return b.eth.txPool.Stats(), 0 +} + +func (b *LesApiBackend) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) { + return b.eth.txPool.Content() +} + +func (b *LesApiBackend) TxPoolContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) { + return b.eth.txPool.ContentFrom(addr) +} + +func (b *LesApiBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { + return b.eth.txPool.SubscribeNewTxsEvent(ch) +} + +func (b *LesApiBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { + return b.eth.blockchain.SubscribeChainEvent(ch) +} + +func (b *LesApiBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { + return b.eth.blockchain.SubscribeChainHeadEvent(ch) +} + +func (b *LesApiBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription { + return b.eth.blockchain.SubscribeChainSideEvent(ch) +} + +func (b *LesApiBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { + return b.eth.blockchain.SubscribeLogsEvent(ch) +} + +func (b *LesApiBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription { + return event.NewSubscription(func(quit <-chan struct{}) error { + <-quit + return nil + }) +} + +func (b *LesApiBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { + return b.eth.blockchain.SubscribeRemovedLogsEvent(ch) +} + +func (b *LesApiBackend) SyncProgress() ethereum.SyncProgress { + return ethereum.SyncProgress{} +} + +func (b *LesApiBackend) ProtocolVersion() int { + return b.eth.LesVersion() + 10000 +} + +func (b *LesApiBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { + return b.gpo.SuggestTipCap(ctx) +} + +func (b *LesApiBackend) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (firstBlock *big.Int, reward [][]*big.Int, baseFee []*big.Int, gasUsedRatio []float64, err error) { + return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles) +} + +func (b *LesApiBackend) ChainDb() ethdb.Database { + return b.eth.chainDb +} + +func (b *LesApiBackend) AccountManager() *accounts.Manager { + return b.eth.accountManager +} + +func (b *LesApiBackend) ExtRPCEnabled() bool { + return b.extRPCEnabled +} + +func (b *LesApiBackend) UnprotectedAllowed() bool { + return b.allowUnprotectedTxs +} + +func (b *LesApiBackend) RPCGasCap() uint64 { + return b.eth.config.RPCGasCap +} + +func (b *LesApiBackend) RPCEVMTimeout() time.Duration { + return b.eth.config.RPCEVMTimeout +} + +func (b *LesApiBackend) RPCTxFeeCap() float64 { + return b.eth.config.RPCTxFeeCap +} + +func (b *LesApiBackend) BloomStatus() (uint64, uint64) { + if b.eth.bloomIndexer == nil { + return 0, 0 + } + sections, _, _ := b.eth.bloomIndexer.Sections() + return params.BloomBitsBlocksClient, sections +} + +func (b *LesApiBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) { + for i := 0; i < bloomFilterThreads; i++ { + go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.eth.bloomRequests) + } +} + +func (b *LesApiBackend) Engine() consensus.Engine { + return b.eth.engine +} + +func (b *LesApiBackend) CurrentHeader() *types.Header { + return b.eth.blockchain.CurrentHeader() +} + +func (b *LesApiBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base vm.StateDB, readOnly bool, preferDisk bool) (vm.StateDB, tracers.StateReleaseFunc, error) { + 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, vm.StateDB, tracers.StateReleaseFunc, error) { + return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) +} diff --git a/miner/miner.go b/miner/miner.go index b7273948f5..57afad41ef 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -27,9 +27,9 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/txpool" "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/event" "github.com/ethereum/go-ethereum/log" @@ -204,7 +204,7 @@ func (miner *Miner) SetRecommitInterval(interval time.Duration) { // Pending returns the currently pending block and associated state. The returned // 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, vm.StateDB) { return miner.worker.pending() } diff --git a/miner/miner_test.go b/miner/miner_test.go index 411d6026ce..4930df773f 100644 --- a/miner/miner_test.go +++ b/miner/miner_test.go @@ -66,7 +66,7 @@ func (m *mockBackend) StateAtBlock(block *types.Block, reexec uint64, base *stat type testBlockChain struct { root common.Hash config *params.ChainConfig - statedb *state.StateDB + statedb vm.StateDB gasLimit uint64 chainHeadFeed *event.Feed } @@ -86,7 +86,7 @@ func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block 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) (vm.StateDB, error) { return bc.statedb, nil } diff --git a/miner/worker.go b/miner/worker.go index f680702814..938d739a49 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -83,9 +83,9 @@ var ( // information of the sealing block generation. type environment struct { signer types.Signer - state *state.StateDB // apply state changes here - tcount int // tx count in cycle - gasPool *core.GasPool // available gas used to pack transactions + state vm.StateDB // apply state changes here + tcount int // tx count in cycle + gasPool *core.GasPool // available gas used to pack transactions coinbase common.Address header *types.Header @@ -125,13 +125,13 @@ func (env *environment) discard() { if env.state == nil { return } - env.state.StopPrefetcher() + env.state.(*state.StateDB).StopPrefetcher() } // task contains all information for consensus engine sealing and result submitting. type task struct { receipts []*types.Receipt - state *state.StateDB + state vm.StateDB block *types.Block createdAt time.Time } @@ -337,7 +337,7 @@ func (w *worker) setRecommitInterval(interval time.Duration) { // pending returns the pending state and corresponding block. The returned // 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, vm.StateDB) { w.snapshotMu.RLock() defer w.snapshotMu.RUnlock() if w.snapshotState == nil { @@ -707,16 +707,16 @@ func (w *worker) resultLoop() { func (w *worker) makeEnv(parent *types.Header, header *types.Header, coinbase common.Address) (*environment, error) { // Retrieve the parent state to execute on top and start a prefetcher for // the miner to speed block sealing up a bit. - state, err := w.chain.StateAt(parent.Root) + stateDB, err := w.chain.StateAt(parent.Root) if err != nil { return nil, err } - state.StartPrefetcher("miner") + stateDB.(*state.StateDB).StartPrefetcher("miner") // Note the passed coinbase may be different with header.Coinbase. env := &environment{ signer: types.MakeSigner(w.chainConfig, header.Number, header.Time), - state: state, + state: stateDB, coinbase: coinbase, header: header, } diff --git a/tests/block_test_util.go b/tests/block_test_util.go index e0130be48a..54bae52845 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -33,7 +33,6 @@ import ( "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" @@ -321,7 +320,7 @@ func validateHeader(h *btHeader, h2 *types.Header) error { return nil } -func (t *BlockTest) validatePostState(statedb *state.StateDB) error { +func (t *BlockTest) validatePostState(statedb vm.StateDB) error { // validate post state accounts in test file against what we have in state db for addr, acct := range t.json.Post { // address is indirectly verified by the other fields, as it's the db key