github.com/ethereum/go-ethereum@v1.16.1/internal/ethapi/override/override.go (about)

     1  // Copyright 2024 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package override
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"math/big"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/common/hexutil"
    26  	"github.com/ethereum/go-ethereum/core/state"
    27  	"github.com/ethereum/go-ethereum/core/tracing"
    28  	"github.com/ethereum/go-ethereum/core/types"
    29  	"github.com/ethereum/go-ethereum/core/vm"
    30  	"github.com/holiman/uint256"
    31  )
    32  
    33  // OverrideAccount indicates the overriding fields of account during the execution
    34  // of a message call.
    35  // Note, state and stateDiff can't be specified at the same time. If state is
    36  // set, message execution will only use the data in the given state. Otherwise
    37  // if stateDiff is set, all diff will be applied first and then execute the call
    38  // message.
    39  type OverrideAccount struct {
    40  	Nonce            *hexutil.Uint64             `json:"nonce"`
    41  	Code             *hexutil.Bytes              `json:"code"`
    42  	Balance          *hexutil.Big                `json:"balance"`
    43  	State            map[common.Hash]common.Hash `json:"state"`
    44  	StateDiff        map[common.Hash]common.Hash `json:"stateDiff"`
    45  	MovePrecompileTo *common.Address             `json:"movePrecompileToAddress"`
    46  }
    47  
    48  // StateOverride is the collection of overridden accounts.
    49  type StateOverride map[common.Address]OverrideAccount
    50  
    51  func (diff *StateOverride) has(address common.Address) bool {
    52  	_, ok := (*diff)[address]
    53  	return ok
    54  }
    55  
    56  // Apply overrides the fields of specified accounts into the given state.
    57  func (diff *StateOverride) Apply(statedb *state.StateDB, precompiles vm.PrecompiledContracts) error {
    58  	if diff == nil {
    59  		return nil
    60  	}
    61  	// Tracks destinations of precompiles that were moved.
    62  	dirtyAddrs := make(map[common.Address]struct{})
    63  	for addr, account := range *diff {
    64  		// If a precompile was moved to this address already, it can't be overridden.
    65  		if _, ok := dirtyAddrs[addr]; ok {
    66  			return fmt.Errorf("account %s has already been overridden by a precompile", addr.Hex())
    67  		}
    68  		p, isPrecompile := precompiles[addr]
    69  		// The MoveTo feature makes it possible to move a precompile
    70  		// code to another address. If the target address is another precompile
    71  		// the code for the latter is lost for this session.
    72  		// Note the destination account is not cleared upon move.
    73  		if account.MovePrecompileTo != nil {
    74  			if !isPrecompile {
    75  				return fmt.Errorf("account %s is not a precompile", addr.Hex())
    76  			}
    77  			// Refuse to move a precompile to an address that has been
    78  			// or will be overridden.
    79  			if diff.has(*account.MovePrecompileTo) {
    80  				return fmt.Errorf("account %s is already overridden", account.MovePrecompileTo.Hex())
    81  			}
    82  			precompiles[*account.MovePrecompileTo] = p
    83  			dirtyAddrs[*account.MovePrecompileTo] = struct{}{}
    84  		}
    85  		if isPrecompile {
    86  			delete(precompiles, addr)
    87  		}
    88  		// Override account nonce.
    89  		if account.Nonce != nil {
    90  			statedb.SetNonce(addr, uint64(*account.Nonce), tracing.NonceChangeUnspecified)
    91  		}
    92  		// Override account(contract) code.
    93  		if account.Code != nil {
    94  			statedb.SetCode(addr, *account.Code)
    95  		}
    96  		// Override account balance.
    97  		if account.Balance != nil {
    98  			u256Balance, _ := uint256.FromBig((*big.Int)(account.Balance))
    99  			statedb.SetBalance(addr, u256Balance, tracing.BalanceChangeUnspecified)
   100  		}
   101  		if account.State != nil && account.StateDiff != nil {
   102  			return fmt.Errorf("account %s has both 'state' and 'stateDiff'", addr.Hex())
   103  		}
   104  		// Replace entire state if caller requires.
   105  		if account.State != nil {
   106  			statedb.SetStorage(addr, account.State)
   107  		}
   108  		// Apply state diff into specified accounts.
   109  		if account.StateDiff != nil {
   110  			for key, value := range account.StateDiff {
   111  				statedb.SetState(addr, key, value)
   112  			}
   113  		}
   114  	}
   115  	// Now finalize the changes. Finalize is normally performed between transactions.
   116  	// By using finalize, the overrides are semantically behaving as
   117  	// if they were created in a transaction just before the tracing occur.
   118  	statedb.Finalise(false)
   119  	return nil
   120  }
   121  
   122  // BlockOverrides is a set of header fields to override.
   123  type BlockOverrides struct {
   124  	Number        *hexutil.Big
   125  	Difficulty    *hexutil.Big // No-op if we're simulating post-merge calls.
   126  	Time          *hexutil.Uint64
   127  	GasLimit      *hexutil.Uint64
   128  	FeeRecipient  *common.Address
   129  	PrevRandao    *common.Hash
   130  	BaseFeePerGas *hexutil.Big
   131  	BlobBaseFee   *hexutil.Big
   132  	BeaconRoot    *common.Hash
   133  	Withdrawals   *types.Withdrawals
   134  }
   135  
   136  // Apply overrides the given header fields into the given block context.
   137  func (o *BlockOverrides) Apply(blockCtx *vm.BlockContext) error {
   138  	if o == nil {
   139  		return nil
   140  	}
   141  	if o.BeaconRoot != nil {
   142  		return errors.New(`block override "beaconRoot" is not supported for this RPC method`)
   143  	}
   144  	if o.Withdrawals != nil {
   145  		return errors.New(`block override "withdrawals" is not supported for this RPC method`)
   146  	}
   147  	if o.Number != nil {
   148  		blockCtx.BlockNumber = o.Number.ToInt()
   149  	}
   150  	if o.Difficulty != nil {
   151  		blockCtx.Difficulty = o.Difficulty.ToInt()
   152  	}
   153  	if o.Time != nil {
   154  		blockCtx.Time = uint64(*o.Time)
   155  	}
   156  	if o.GasLimit != nil {
   157  		blockCtx.GasLimit = uint64(*o.GasLimit)
   158  	}
   159  	if o.FeeRecipient != nil {
   160  		blockCtx.Coinbase = *o.FeeRecipient
   161  	}
   162  	if o.PrevRandao != nil {
   163  		blockCtx.Random = o.PrevRandao
   164  	}
   165  	if o.BaseFeePerGas != nil {
   166  		blockCtx.BaseFee = o.BaseFeePerGas.ToInt()
   167  	}
   168  	if o.BlobBaseFee != nil {
   169  		blockCtx.BlobBaseFee = o.BlobBaseFee.ToInt()
   170  	}
   171  	return nil
   172  }
   173  
   174  // MakeHeader returns a new header object with the overridden
   175  // fields.
   176  // Note: MakeHeader ignores BlobBaseFee if set. That's because
   177  // header has no such field.
   178  func (o *BlockOverrides) MakeHeader(header *types.Header) *types.Header {
   179  	if o == nil {
   180  		return header
   181  	}
   182  	h := types.CopyHeader(header)
   183  	if o.Number != nil {
   184  		h.Number = o.Number.ToInt()
   185  	}
   186  	if o.Difficulty != nil {
   187  		h.Difficulty = o.Difficulty.ToInt()
   188  	}
   189  	if o.Time != nil {
   190  		h.Time = uint64(*o.Time)
   191  	}
   192  	if o.GasLimit != nil {
   193  		h.GasLimit = uint64(*o.GasLimit)
   194  	}
   195  	if o.FeeRecipient != nil {
   196  		h.Coinbase = *o.FeeRecipient
   197  	}
   198  	if o.PrevRandao != nil {
   199  		h.MixDigest = *o.PrevRandao
   200  	}
   201  	if o.BaseFeePerGas != nil {
   202  		h.BaseFee = o.BaseFeePerGas.ToInt()
   203  	}
   204  	return h
   205  }