From b73207705b1289baae45381446bf5454abbd2d39 Mon Sep 17 00:00:00 2001 From: Sina Mahmoodi Date: Tue, 19 Mar 2024 18:42:32 +0100 Subject: [PATCH] refactor args to msg and tx # Conflicts: # internal/ethapi/api.go # internal/ethapi/transaction_args.go --- eth/tracers/api.go | 64 ++--------------- internal/ethapi/api.go | 10 +-- internal/ethapi/transaction_args.go | 104 ++++++++++++++++------------ 3 files changed, 71 insertions(+), 107 deletions(-) diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 7cab53d1c5..4c19879594 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -926,15 +926,14 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc config.BlockOverrides.Apply(&vmctx) } // Execute the trace - msg, err := args.ToMessage(api.backend.RPCGasCap(), vmctx.BaseFee) - if err != nil { + if err := args.CallDefaults(api.backend.RPCGasCap(), vmctx.BaseFee, api.backend.ChainConfig().ChainID); err != nil { return nil, err } - tx, err := argsToTransaction(api.backend, &args, msg) - if err != nil { - return nil, err - } - var traceConfig *TraceConfig + var ( + msg = args.ToMessage(vmctx.BaseFee) + tx = args.ToTransaction() + traceConfig *TraceConfig + ) if config != nil { traceConfig = &config.TraceConfig } @@ -1050,54 +1049,3 @@ func overrideConfig(original *params.ChainConfig, override *params.ChainConfig) return copy, canon } - -// argsToTransaction produces a Transaction object given call arguments. -// The `msg` field must be converted from the same arguments. -func argsToTransaction(b Backend, args *ethapi.TransactionArgs, msg *core.Message) (*types.Transaction, error) { - chainID := b.ChainConfig().ChainID - if args.ChainID != nil { - if have := (*big.Int)(args.ChainID); have.Cmp(chainID) != 0 { - return nil, fmt.Errorf("chainId does not match node's (have=%v, want=%v)", have, chainID) - } - } - var data types.TxData - switch { - case args.MaxFeePerGas != nil: - al := types.AccessList{} - if args.AccessList != nil { - al = *args.AccessList - } - data = &types.DynamicFeeTx{ - To: args.To, - ChainID: chainID, - Nonce: msg.Nonce, - Gas: msg.GasLimit, - GasFeeCap: msg.GasFeeCap, - GasTipCap: msg.GasTipCap, - Value: msg.Value, - Data: msg.Data, - AccessList: al, - } - case args.AccessList != nil: - data = &types.AccessListTx{ - To: args.To, - ChainID: chainID, - Nonce: msg.Nonce, - Gas: msg.GasLimit, - GasPrice: msg.GasPrice, - Value: msg.Value, - Data: msg.Data, - AccessList: *args.AccessList, - } - default: - data = &types.LegacyTx{ - To: args.To, - Nonce: msg.Nonce, - Gas: msg.GasLimit, - GasPrice: msg.GasPrice, - Value: msg.Value, - Data: msg.Data, - } - } - return types.NewTx(data), nil -} diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index d1ac21b9d8..11ac7cf611 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1076,14 +1076,14 @@ func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.S defer cancel() // Get a new instance of the EVM. - msg, err := args.ToMessage(globalGasCap, header.BaseFee) - if err != nil { - return nil, err - } blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil) if blockOverrides != nil { blockOverrides.Apply(&blockCtx) } + if err := args.CallDefaults(globalGasCap, blockCtx.BaseFee, b.ChainConfig().ChainID); err != nil { + return nil, err + } + msg := args.ToMessage(blockCtx.BaseFee) evm, vmError := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, &blockCtx) // Wait for the context to be done and cancel the evm. Even if the @@ -1633,7 +1633,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH statedb := db.Copy() // Set the accesslist to the last al args.AccessList = &accessList - msg, err := args.ToMessage(b.RPCGasCap(), header.BaseFee) + msg := args.ToMessage(header.BaseFee) if err != nil { return nil, 0, nil, err } diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index e4cf81a3f4..ee13f9cc6b 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -197,40 +197,68 @@ func (args *TransactionArgs) setLondonFeeDefaults(ctx context.Context, head *typ return nil } +// CallDefaults sanitizes the transaction arguments, often filling in zero values, +// for the purpose of eth_call class of RPC methods. +func (args *TransactionArgs) CallDefaults(globalGasCap uint64, baseFee *big.Int, chainID *big.Int) error { + // Reject invalid combinations of pre- and post-1559 fee styles + if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { + return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") + } + if args.ChainID == nil { + args.ChainID = (*hexutil.Big)(chainID) + } else { + if have := (*big.Int)(args.ChainID); have.Cmp(chainID) != 0 { + return fmt.Errorf("chainId does not match node's (have=%v, want=%v)", have, chainID) + } + } + if args.Gas == nil { + gas := globalGasCap + if gas == 0 { + gas = uint64(math.MaxUint64 / 2) + } + args.Gas = (*hexutil.Uint64)(&gas) + } else { + if globalGasCap > 0 && globalGasCap < uint64(*args.Gas) { + log.Warn("Caller gas above allowance, capping", "requested", args.Gas, "cap", globalGasCap) + args.Gas = (*hexutil.Uint64)(&globalGasCap) + } + } + if args.Nonce == nil { + args.Nonce = new(hexutil.Uint64) + } + if args.Value == nil { + args.Value = new(hexutil.Big) + } + if baseFee == nil { + // If there's no basefee, then it must be a non-1559 execution + if args.GasPrice == nil { + args.GasPrice = new(hexutil.Big) + } + } else { + // A basefee is provided, necessitating 1559-type execution + if args.MaxFeePerGas == nil { + args.MaxFeePerGas = new(hexutil.Big) + } + if args.MaxPriorityFeePerGas == nil { + args.MaxPriorityFeePerGas = new(hexutil.Big) + } + } + + return nil +} + // ToMessage converts the transaction arguments to the Message type used by the // core evm. This method is used in calls and traces that do not require a real // live transaction. -func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*core.Message, error) { - // Reject invalid combinations of pre- and post-1559 fee styles - if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { - return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") - } - // Set sender address or use zero address if none specified. - addr := args.from() - - // Set default gas & gas price if none were set - gas := globalGasCap - if gas == 0 { - gas = uint64(math.MaxUint64 / 2) - } - if args.Gas != nil { - gas = uint64(*args.Gas) - } - if globalGasCap != 0 && globalGasCap < gas { - log.Warn("Caller gas above allowance, capping", "requested", gas, "cap", globalGasCap) - gas = globalGasCap - } +// Assumes that fields are not nil, i.e. setDefaults or CallDefaults has been called. +func (args *TransactionArgs) ToMessage(baseFee *big.Int) *core.Message { var ( gasPrice *big.Int gasFeeCap *big.Int gasTipCap *big.Int ) if baseFee == nil { - // If there's no basefee, then it must be a non-1559 execution - gasPrice = new(big.Int) - if args.GasPrice != nil { - gasPrice = args.GasPrice.ToInt() - } + gasPrice = args.GasPrice.ToInt() gasFeeCap, gasTipCap = gasPrice, gasPrice } else { // A basefee is provided, necessitating 1559-type execution @@ -240,14 +268,8 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (* gasFeeCap, gasTipCap = gasPrice, gasPrice } else { // User specified 1559 gas fields (or none), use those - gasFeeCap = new(big.Int) - if args.MaxFeePerGas != nil { - gasFeeCap = args.MaxFeePerGas.ToInt() - } - gasTipCap = new(big.Int) - if args.MaxPriorityFeePerGas != nil { - gasTipCap = args.MaxPriorityFeePerGas.ToInt() - } + gasFeeCap = args.MaxFeePerGas.ToInt() + gasTipCap = args.MaxPriorityFeePerGas.ToInt() // Backfill the legacy gasPrice for EVM execution, unless we're all zeroes gasPrice = new(big.Int) if gasFeeCap.BitLen() > 0 || gasTipCap.BitLen() > 0 { @@ -255,28 +277,22 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (* } } } - value := new(big.Int) - if args.Value != nil { - value = args.Value.ToInt() - } - data := args.data() var accessList types.AccessList if args.AccessList != nil { accessList = *args.AccessList } - msg := &core.Message{ - From: addr, + return &core.Message{ + From: args.from(), To: args.To, - Value: value, - GasLimit: gas, + Value: (*big.Int)(args.Value), + GasLimit: uint64(*args.Gas), GasPrice: gasPrice, GasFeeCap: gasFeeCap, GasTipCap: gasTipCap, - Data: data, + Data: args.data(), AccessList: accessList, SkipAccountChecks: true, } - return msg, nil } // toTransaction converts the arguments to a transaction.