mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
refactor
This commit is contained in:
parent
6735dde9ed
commit
c0667ed1da
18 changed files with 66 additions and 183 deletions
|
|
@ -304,7 +304,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
statedb.AddBalance(w.Address, amount)
|
||||
}
|
||||
// Commit block
|
||||
root, err := statedb.Commit(vmContext.BlockNumber.Uint64(), chainConfig.IsEIP158(vmContext.BlockNumber))
|
||||
root, _, err := statedb.Commit(vmContext.BlockNumber.Uint64(), chainConfig.IsEIP158(vmContext.BlockNumber))
|
||||
if err != nil {
|
||||
return nil, nil, NewError(ErrorEVM, fmt.Errorf("could not commit state: %v", err))
|
||||
}
|
||||
|
|
@ -349,7 +349,7 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB
|
|||
}
|
||||
}
|
||||
// Commit and re-open to start with a clean state.
|
||||
root, _ := statedb.Commit(0, false)
|
||||
root, _, _ := statedb.Commit(0, false)
|
||||
statedb, _ = state.New(root, sdb, nil)
|
||||
return statedb
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1407,7 +1407,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
|||
log.Crit("Failed to write block into disk", "err", err)
|
||||
}
|
||||
// Commit all cached state changes into underlying memory database.
|
||||
root, err := state.Commit(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number()))
|
||||
root, _, err := state.Commit(block.NumberU64(), bc.chainConfig.IsEIP158(block.Number()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
|||
}
|
||||
|
||||
// Write state changes to db
|
||||
root, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number))
|
||||
root, _, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("state write error: %v", err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,7 +139,8 @@ func (ga *GenesisAlloc) deriveHash() (common.Hash, error) {
|
|||
statedb.SetState(addr, key, value)
|
||||
}
|
||||
}
|
||||
return statedb.Commit(0, false)
|
||||
root, _, err := statedb.Commit(0, false)
|
||||
return root, err
|
||||
}
|
||||
|
||||
// flush is very similar with deriveHash, but the main difference is
|
||||
|
|
@ -160,7 +161,7 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas
|
|||
statedb.SetState(addr, key, value)
|
||||
}
|
||||
}
|
||||
root, err := statedb.Commit(0, false)
|
||||
root, _, err := statedb.Commit(0, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,8 +75,6 @@ type Trie interface {
|
|||
// a trie.MissingNodeError is returned.
|
||||
GetStorage(addr common.Address, key []byte) ([]byte, error)
|
||||
|
||||
GetWitness() *trienode.Witness
|
||||
|
||||
// GetAccount abstracts an account read from the trie. It retrieves the
|
||||
// account blob from the trie with provided account address and decodes it
|
||||
// with associated decoding algorithm. If the specified account is not in
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ func TestDump(t *testing.T) {
|
|||
// write some of them to the trie
|
||||
s.state.updateStateObject(obj1)
|
||||
s.state.updateStateObject(obj2)
|
||||
root, _ := s.state.Commit(0, false)
|
||||
root, _, _ := s.state.Commit(0, false)
|
||||
|
||||
// check that DumpToCollector contains the state objects that are in trie
|
||||
s.state, _ = New(root, tdb, nil)
|
||||
|
|
@ -114,7 +114,7 @@ func TestIterativeDump(t *testing.T) {
|
|||
// write some of them to the trie
|
||||
s.state.updateStateObject(obj1)
|
||||
s.state.updateStateObject(obj2)
|
||||
root, _ := s.state.Commit(0, false)
|
||||
root, _, _ := s.state.Commit(0, false)
|
||||
s.state, _ = New(root, tdb, nil)
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
|
|
@ -212,7 +212,7 @@ func TestSnapshot2(t *testing.T) {
|
|||
so0.deleted = false
|
||||
state.setStateObject(so0)
|
||||
|
||||
root, _ := state.Commit(0, false)
|
||||
root, _, _ := state.Commit(0, false)
|
||||
state, _ = New(root, state.db, state.snaps)
|
||||
|
||||
// and one with deleted == true
|
||||
|
|
|
|||
|
|
@ -172,14 +172,6 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error)
|
|||
return sdb, nil
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
// commit phase, most of the needed data is already hot.
|
||||
func (s *StateDB) GetWitness() *trienode.Witness {
|
||||
return s.trie.GetWitness()
|
||||
}
|
||||
|
||||
func (s *StateDB) CleanSnaps() {
|
||||
s.snaps = nil
|
||||
s.snap = nil
|
||||
|
|
@ -1175,10 +1167,10 @@ func (s *StateDB) handleDestruction(nodes *trienode.MergedNodeSet) (map[common.A
|
|||
//
|
||||
// The associated block number of the state transition is also provided
|
||||
// for more chain context.
|
||||
func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, error) {
|
||||
func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, *trienode.Witnesses, error) {
|
||||
// Short circuit in case any database failure occurred earlier.
|
||||
if s.dbErr != nil {
|
||||
return common.Hash{}, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr)
|
||||
return common.Hash{}, nil, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr)
|
||||
}
|
||||
// Finalize any pending changes and merge everything into the tries
|
||||
s.IntermediateRoot(deleteEmptyObjects)
|
||||
|
|
@ -1196,7 +1188,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
|
|||
// Handle all state deletions first
|
||||
incomplete, err := s.handleDestruction(nodes)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
return common.Hash{}, nil, err
|
||||
}
|
||||
// Handle all state updates afterwards
|
||||
for addr := range s.stateObjectsDirty {
|
||||
|
|
@ -1212,20 +1204,21 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
|
|||
// Write any storage changes in the state object to its storage trie
|
||||
set, witness, err := obj.commit()
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
return common.Hash{}, nil, err
|
||||
}
|
||||
// Merge the dirty nodes of storage trie into global set. It is possible
|
||||
// that the account was destructed and then resurrected in the same block.
|
||||
// In this case, the node set is shared by both accounts.
|
||||
if set != nil {
|
||||
if err := nodes.Merge(set); err != nil {
|
||||
return common.Hash{}, err
|
||||
return common.Hash{}, nil, err
|
||||
}
|
||||
updates, deleted := set.Size()
|
||||
storageTrieNodesUpdated += updates
|
||||
storageTrieNodesDeleted += deleted
|
||||
}
|
||||
if witness != nil {
|
||||
fmt.Printf("witness owner: %x, witness len: %d\n", witness.Owner, len(witness.Nodes))
|
||||
witnesses.Merge(witness)
|
||||
}
|
||||
}
|
||||
|
|
@ -1241,12 +1234,12 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
|
|||
}
|
||||
root, set, witness, err := s.trie.Commit(true)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
return common.Hash{}, nil, err
|
||||
}
|
||||
// Merge the dirty nodes of account trie into global set
|
||||
if set != nil {
|
||||
if err := nodes.Merge(set); err != nil {
|
||||
return common.Hash{}, err
|
||||
return common.Hash{}, nil, err
|
||||
}
|
||||
accountTrieNodesUpdated, accountTrieNodesDeleted = set.Size()
|
||||
}
|
||||
|
|
@ -1299,7 +1292,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
|
|||
start := time.Now()
|
||||
set := triestate.New(s.accountsOrigin, s.storagesOrigin, incomplete)
|
||||
if err := s.db.TrieDB().Update(root, origin, block, nodes, set); err != nil {
|
||||
return common.Hash{}, err
|
||||
return common.Hash{}, nil, err
|
||||
}
|
||||
s.originalRoot = root
|
||||
if metrics.EnabledExpensive {
|
||||
|
|
@ -1316,7 +1309,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
|
|||
s.storagesOrigin = make(map[common.Address]map[common.Hash][]byte)
|
||||
s.stateObjectsDirty = make(map[common.Address]struct{})
|
||||
s.stateObjectsDestruct = make(map[common.Address]*types.StateAccount)
|
||||
return root, nil
|
||||
return root, witnesses, nil
|
||||
}
|
||||
|
||||
// Prepare handles the preparatory steps for executing a state transition with.
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ func (test *stateTest) run() bool {
|
|||
} else {
|
||||
state.IntermediateRoot(true) // call intermediateRoot at the transaction boundary
|
||||
}
|
||||
nroot, err := state.Commit(0, true) // call commit at the block boundary
|
||||
nroot, _, err := state.Commit(0, true) // call commit at the block boundary
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ func TestIntermediateLeaks(t *testing.T) {
|
|||
}
|
||||
|
||||
// Commit and cross check the databases.
|
||||
transRoot, err := transState.Commit(0, false)
|
||||
transRoot, _, err := transState.Commit(0, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to commit transition state: %v", err)
|
||||
}
|
||||
|
|
@ -124,7 +124,7 @@ func TestIntermediateLeaks(t *testing.T) {
|
|||
t.Errorf("can not commit trie %v to persistent database", transRoot.Hex())
|
||||
}
|
||||
|
||||
finalRoot, err := finalState.Commit(0, false)
|
||||
finalRoot, _, err := finalState.Commit(0, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to commit final state: %v", err)
|
||||
}
|
||||
|
|
@ -534,7 +534,7 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error {
|
|||
func TestTouchDelete(t *testing.T) {
|
||||
s := newStateEnv()
|
||||
s.state.GetOrNewStateObject(common.Address{})
|
||||
root, _ := s.state.Commit(0, false)
|
||||
root, _, _ := s.state.Commit(0, false)
|
||||
s.state, _ = New(root, s.state.db, s.state.snaps)
|
||||
|
||||
snapshot := s.state.Snapshot()
|
||||
|
|
@ -622,7 +622,7 @@ func TestCopyCommitCopy(t *testing.T) {
|
|||
t.Fatalf("second copy committed storage slot mismatch: have %x, want %x", val, sval)
|
||||
}
|
||||
// Commit state, ensure states can be loaded from disk
|
||||
root, _ := state.Commit(0, false)
|
||||
root, _, _ := state.Commit(0, false)
|
||||
state, _ = New(root, tdb, nil)
|
||||
if balance := state.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 {
|
||||
t.Fatalf("state post-commit balance mismatch: have %v, want %v", balance, 42)
|
||||
|
|
@ -770,7 +770,7 @@ func TestDeleteCreateRevert(t *testing.T) {
|
|||
addr := common.BytesToAddress([]byte("so"))
|
||||
state.SetBalance(addr, big.NewInt(1))
|
||||
|
||||
root, _ := state.Commit(0, false)
|
||||
root, _, _ := state.Commit(0, false)
|
||||
state, _ = New(root, state.db, state.snaps)
|
||||
|
||||
// Simulate self-destructing in one transaction, then create-reverting in another
|
||||
|
|
@ -782,7 +782,7 @@ func TestDeleteCreateRevert(t *testing.T) {
|
|||
state.RevertToSnapshot(id)
|
||||
|
||||
// Commit the entire state and make sure we don't crash and have the correct state
|
||||
root, _ = state.Commit(0, true)
|
||||
root, _, _ = state.Commit(0, true)
|
||||
state, _ = New(root, state.db, state.snaps)
|
||||
|
||||
if state.getStateObject(addr) != nil {
|
||||
|
|
@ -825,7 +825,7 @@ func testMissingTrieNodes(t *testing.T, scheme string) {
|
|||
a2 := common.BytesToAddress([]byte("another"))
|
||||
state.SetBalance(a2, big.NewInt(100))
|
||||
state.SetCode(a2, []byte{1, 2, 4})
|
||||
root, _ = state.Commit(0, false)
|
||||
root, _, _ = state.Commit(0, false)
|
||||
t.Logf("root: %x", root)
|
||||
// force-flush
|
||||
triedb.Commit(root, false)
|
||||
|
|
@ -849,7 +849,7 @@ func testMissingTrieNodes(t *testing.T, scheme string) {
|
|||
}
|
||||
// Modify the state
|
||||
state.SetBalance(addr, big.NewInt(2))
|
||||
root, err := state.Commit(0, false)
|
||||
root, _, err := state.Commit(0, false)
|
||||
if err == nil {
|
||||
t.Fatalf("expected error, got root :%x", root)
|
||||
}
|
||||
|
|
@ -1045,7 +1045,7 @@ func TestFlushOrderDataLoss(t *testing.T) {
|
|||
state.SetState(common.Address{a}, common.Hash{a, s}, common.Hash{a, s})
|
||||
}
|
||||
}
|
||||
root, err := state.Commit(0, false)
|
||||
root, _, err := state.Commit(0, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to commit state trie: %v", err)
|
||||
}
|
||||
|
|
@ -1124,7 +1124,7 @@ func TestResetObject(t *testing.T) {
|
|||
state.CreateAccount(addr)
|
||||
state.SetBalance(addr, big.NewInt(2))
|
||||
state.SetState(addr, slotB, common.BytesToHash([]byte{0x2}))
|
||||
root, _ := state.Commit(0, true)
|
||||
root, _, _ := state.Commit(0, true)
|
||||
|
||||
// Ensure the original account is wiped properly
|
||||
snap := snaps.Snapshot(root)
|
||||
|
|
@ -1155,7 +1155,7 @@ func TestDeleteStorage(t *testing.T) {
|
|||
value := common.Hash(uint256.NewInt(uint64(10 * i)).Bytes32())
|
||||
state.SetState(addr, slot, value)
|
||||
}
|
||||
root, _ := state.Commit(0, true)
|
||||
root, _, _ := state.Commit(0, true)
|
||||
// Init phase done, create two states, one with snap and one without
|
||||
fastState, _ := New(root, db, snaps)
|
||||
slowState, _ := New(root, db, nil)
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ func makeTestState(scheme string) (ethdb.Database, Database, *trie.Database, com
|
|||
}
|
||||
accounts = append(accounts, acc)
|
||||
}
|
||||
root, _ := state.Commit(0, false)
|
||||
root, _, _ := state.Commit(0, false)
|
||||
|
||||
// Return the generated state
|
||||
return db, sdb, nodeDb, root, accounts
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ func TestAccountRange(t *testing.T) {
|
|||
m[addr] = true
|
||||
}
|
||||
}
|
||||
root, _ := sdb.Commit(0, true)
|
||||
root, _, _ := sdb.Commit(0, true)
|
||||
sdb, _ = state.New(root, statedb, nil)
|
||||
|
||||
trie, err := statedb.OpenTrie(root)
|
||||
|
|
@ -178,7 +178,7 @@ func TestStorageRangeAt(t *testing.T) {
|
|||
for _, entry := range storage {
|
||||
sdb.SetState(addr, *entry.Key, entry.Value)
|
||||
}
|
||||
root, _ := sdb.Commit(0, false)
|
||||
root, _, _ := sdb.Commit(0, false)
|
||||
sdb, _ = state.New(root, db, nil)
|
||||
|
||||
// Check a few combinations of limit and start/end.
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
|
|||
return nil, nil, fmt.Errorf("processing block %d failed: %v", current.NumberU64(), err)
|
||||
}
|
||||
// Finalize the state so any modifications are written to the trie
|
||||
root, err := statedb.Commit(current.NumberU64(), eth.blockchain.Config().IsEIP158(current.Number()))
|
||||
root, _, err := statedb.Commit(current.NumberU64(), eth.blockchain.Config().IsEIP158(current.Number()))
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("stateAtBlock commit failed, number %d root %v: %w",
|
||||
current.NumberU64(), current.Root().Hex(), err)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ package ethapi
|
|||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
|
@ -962,35 +961,29 @@ type RecentBlockHash struct {
|
|||
}
|
||||
|
||||
// GetRequiredBlockState returns all state required to execute a single historical block.
|
||||
func (s *BlockChainAPI) GetRequiredBlockState(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*trienode.Witness, error) {
|
||||
func (s *BlockChainAPI) GetRequiredBlockState(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (map[common.Hash]*trienode.Witness, error) {
|
||||
block, err := s.b.BlockByNumberOrHash(ctx, blockNrOrHash)
|
||||
if block == nil || err != nil {
|
||||
// When the block doesn't exist, the RPC method should return JSON null
|
||||
return nil, nil
|
||||
}
|
||||
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||
parentHash := block.ParentHash()
|
||||
state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, rpc.BlockNumberOrHash{BlockHash: &parentHash})
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
state.CleanSnaps()
|
||||
s.ProcessBlock(ctx, block, state, vm.Config{})
|
||||
return state.GetWitness(), nil
|
||||
// return s.traceBlock(ctx, block)
|
||||
}
|
||||
if err := s.ProcessBlock(ctx, block, state, vm.Config{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, witnesses, err := state.Commit(block.NumberU64(), true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// txTraceResult is the result of a single transaction trace.
|
||||
type txTraceResult struct {
|
||||
TxHash common.Hash `json:"txHash"` // transaction hash
|
||||
Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer
|
||||
Error string `json:"error,omitempty"` // Trace failure produced by the tracer
|
||||
return witnesses.Witnesses(), nil
|
||||
}
|
||||
|
||||
const (
|
||||
// defaultTraceTimeout is the amount of time a single transaction can execute
|
||||
// by default before being forcefully aborted.
|
||||
defaultTraceTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
// 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.
|
||||
|
|
@ -998,14 +991,10 @@ const (
|
|||
// 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 (s *BlockChainAPI) ProcessBlock(ctx context.Context, block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) {
|
||||
func (s *BlockChainAPI) ProcessBlock(ctx context.Context, block *types.Block, statedb *state.StateDB, cfg vm.Config) error {
|
||||
var (
|
||||
receipts types.Receipts
|
||||
usedGas = new(uint64)
|
||||
header = block.Header()
|
||||
blockHash = block.Hash()
|
||||
blockNumber = block.Number()
|
||||
allLogs []*types.Log
|
||||
gp = new(core.GasPool).AddGas(block.GasLimit())
|
||||
)
|
||||
var (
|
||||
|
|
@ -1020,26 +1009,19 @@ func (s *BlockChainAPI) ProcessBlock(ctx context.Context, block *types.Block, st
|
|||
for i, tx := range block.Transactions() {
|
||||
msg, err := core.TransactionToMessage(tx, signer, header.BaseFee)
|
||||
if err != nil {
|
||||
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||
return fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||
}
|
||||
statedb.SetTxContext(tx.Hash(), i)
|
||||
receipt, err := applyTransaction(msg, s.b.ChainConfig(), gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv)
|
||||
err = applyTransaction(msg, gp, statedb, usedGas, vmenv)
|
||||
if err != nil {
|
||||
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||
return fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||
}
|
||||
receipts = append(receipts, receipt)
|
||||
allLogs = append(allLogs, receipt.Logs...)
|
||||
}
|
||||
// Fail if Shanghai not enabled and len(withdrawals) is non-zero.
|
||||
withdrawals := block.Withdrawals()
|
||||
if len(withdrawals) > 0 && !s.b.ChainConfig().IsShanghai(block.Number(), block.Time()) {
|
||||
return nil, nil, 0, errors.New("withdrawals before shanghai")
|
||||
}
|
||||
|
||||
return receipts, allLogs, *usedGas, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func applyTransaction(msg *core.Message, config *params.ChainConfig, gp *core.GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) {
|
||||
func applyTransaction(msg *core.Message, gp *core.GasPool, statedb *state.StateDB, usedGas *uint64, evm *vm.EVM) error {
|
||||
// Create a new context to be used in the EVM environment.
|
||||
txContext := core.NewEVMTxContext(msg)
|
||||
evm.Reset(txContext, statedb)
|
||||
|
|
@ -1047,98 +1029,14 @@ func applyTransaction(msg *core.Message, config *params.ChainConfig, gp *core.Ga
|
|||
// Apply the transaction to the current state (included in the env).
|
||||
result, err := core.ApplyMessage(evm, msg, gp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// Update the state with pending changes.
|
||||
var root []byte
|
||||
if config.IsByzantium(blockNumber) {
|
||||
statedb.Finalise(true)
|
||||
} else {
|
||||
root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).Bytes()
|
||||
}
|
||||
*usedGas += result.UsedGas
|
||||
|
||||
_ = root
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// traceBlock configures a new tracer according to the provided configuration, and
|
||||
// executes all the transactions contained within. The return value will be one item
|
||||
// per transaction, dependent on the requested tracer.
|
||||
func (s *BlockChainAPI) traceBlock(ctx context.Context, block *types.Block) ([]*txTraceResult, error) {
|
||||
if block.NumberU64() == 0 {
|
||||
return nil, errors.New("genesis is not traceable")
|
||||
}
|
||||
// Prepare base state
|
||||
statedb, _, err := s.b.StateAndHeaderByNumber(ctx, rpc.BlockNumber(block.NumberU64()-1))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Native tracers have low overhead
|
||||
var (
|
||||
txs = block.Transactions()
|
||||
is158 = s.b.ChainConfig().IsEIP158(block.Number())
|
||||
blockCtx = core.NewEVMBlockContext(block.Header(), NewChainContext(ctx, s.b), nil)
|
||||
signer = types.MakeSigner(s.b.ChainConfig(), block.Number(), block.Time())
|
||||
results = make([]*txTraceResult, len(txs))
|
||||
)
|
||||
for i, tx := range txs {
|
||||
// Generate the next state snapshot fast without tracing
|
||||
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
|
||||
res, err := s.traceTx(ctx, msg, blockCtx, statedb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results[i] = &txTraceResult{TxHash: tx.Hash(), Result: res}
|
||||
// Finalize the state so any modifications are written to the trie
|
||||
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
||||
statedb.Finalise(is158)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// Tracer interface extends vm.EVMLogger and additionally
|
||||
// allows collecting the tracing result.
|
||||
type Tracer interface {
|
||||
vm.EVMLogger
|
||||
GetResult() (json.RawMessage, error)
|
||||
// Stop terminates execution of the tracer at the first opportune moment.
|
||||
Stop(err error)
|
||||
}
|
||||
|
||||
// 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 (s *BlockChainAPI) traceTx(ctx context.Context, message *core.Message, vmctx vm.BlockContext, statedb *state.StateDB) (interface{}, error) {
|
||||
var (
|
||||
tracer Tracer
|
||||
err error
|
||||
timeout = defaultTraceTimeout
|
||||
txContext = core.NewEVMTxContext(message)
|
||||
)
|
||||
// Default tracer is the struct logger
|
||||
tracer = logger.NewStructLogger(&logger.Config{})
|
||||
vmenv := vm.NewEVM(vmctx, txContext, statedb, s.b.ChainConfig(), vm.Config{Tracer: tracer, NoBaseFee: true})
|
||||
|
||||
// Define a meaningful timeout of a single transaction trace
|
||||
deadlineCtx, cancel := context.WithTimeout(ctx, timeout)
|
||||
go func() {
|
||||
<-deadlineCtx.Done()
|
||||
if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) {
|
||||
tracer.Stop(errors.New("execution timeout"))
|
||||
// Stop evm execution. Note cancellation is not necessarily immediate.
|
||||
vmenv.Cancel()
|
||||
}
|
||||
}()
|
||||
defer cancel()
|
||||
|
||||
// Call Prepare to clear out the statedb access list
|
||||
if _, err = core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.GasLimit)); err != nil {
|
||||
return nil, fmt.Errorf("tracing failed: %w", err)
|
||||
}
|
||||
return tracer.GetResult()
|
||||
return err
|
||||
}
|
||||
|
||||
// OverrideAccount indicates the overriding fields of account during the execution
|
||||
|
|
|
|||
|
|
@ -106,10 +106,6 @@ type odrTrie struct {
|
|||
trie *trie.Trie
|
||||
}
|
||||
|
||||
func (t *odrTrie) GetWitness() *trienode.Witness {
|
||||
return t.trie.GetWitness()
|
||||
}
|
||||
|
||||
func (t *odrTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) {
|
||||
key = crypto.Keccak256(key)
|
||||
var enc []byte
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
|||
statedb.AddBalance(block.Coinbase(), new(big.Int))
|
||||
|
||||
// Commit state mutations into database.
|
||||
root, _ := statedb.Commit(block.NumberU64(), config.IsEIP158(block.Number()))
|
||||
root, _, _ := statedb.Commit(block.NumberU64(), config.IsEIP158(block.Number()))
|
||||
return triedb, snaps, statedb, root, err
|
||||
}
|
||||
|
||||
|
|
@ -325,7 +325,7 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter boo
|
|||
}
|
||||
}
|
||||
// Commit and re-open to start with a clean state.
|
||||
root, _ := statedb.Commit(0, false)
|
||||
root, _, _ := statedb.Commit(0, false)
|
||||
|
||||
var snaps *snapshot.Tree
|
||||
if snapshotter {
|
||||
|
|
|
|||
|
|
@ -81,10 +81,6 @@ func (t *StateTrie) MustGet(key []byte) []byte {
|
|||
return t.trie.MustGet(t.hashKey(key))
|
||||
}
|
||||
|
||||
func (t *StateTrie) GetWitness() *trienode.Witness {
|
||||
return t.trie.GetWitness()
|
||||
}
|
||||
|
||||
// GetStorage attempts to retrieve a storage slot with provided account address
|
||||
// and slot key. The value bytes must not be modified by the caller.
|
||||
// If the specified storage slot is not in the trie, nil will be returned.
|
||||
|
|
|
|||
|
|
@ -688,7 +688,3 @@ func (t *Trie) Reset() {
|
|||
t.witness = trienode.NewWitness(common.Hash{})
|
||||
t.committed = false
|
||||
}
|
||||
|
||||
func (t *Trie) GetWitness() *trienode.Witness {
|
||||
return t.witness
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,8 +101,13 @@ func NewWitnesses() *Witnesses {
|
|||
func (set *Witnesses) Merge(other *Witness) error {
|
||||
_, present := set.witness[other.Owner]
|
||||
if present {
|
||||
return nil
|
||||
//return subset.Merge(other.Owner, other.Nodes)
|
||||
}
|
||||
set.witness[other.Owner] = other
|
||||
return nil
|
||||
}
|
||||
|
||||
func (set *Witnesses) Witnesses() map[common.Hash]*Witness {
|
||||
return set.witness
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue