diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 445f476cf..f928621a1 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -476,7 +476,8 @@ var ( } RPCGlobalGasCap = cli.Uint64Flag{ Name: "rpc.gascap", - Usage: "Sets a cap on gas that can be used in eth_call/estimateGas", + Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)", + Value: eth.DefaultConfig.RPCGasCap, } RPCGlobalTxFeeCap = cli.Float64Flag{ Name: "rpc.txfeecap", @@ -1563,7 +1564,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { cfg.EVMInterpreter = ctx.GlobalString(EVMInterpreterFlag.Name) } if ctx.GlobalIsSet(RPCGlobalGasCap.Name) { - cfg.RPCGasCap = new(big.Int).SetUint64(ctx.GlobalUint64(RPCGlobalGasCap.Name)) + cfg.RPCGasCap = ctx.GlobalUint64(RPCGlobalGasCap.Name) + } + if cfg.RPCGasCap != 0 { + log.Info("Set global gas cap", "cap", cfg.RPCGasCap) + } else { + log.Info("Global gas cap disabled") } if ctx.GlobalIsSet(RPCGlobalTxFeeCap.Name) { cfg.RPCTxFeeCap = ctx.GlobalFloat64(RPCGlobalTxFeeCap.Name) diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go index be06577e3..c436a309f 100644 --- a/core/tx_pool_test.go +++ b/core/tx_pool_test.go @@ -18,6 +18,7 @@ package core import ( "crypto/ecdsa" + "errors" "fmt" "io/ioutil" "math/big" @@ -245,7 +246,7 @@ func TestInvalidTransactions(t *testing.T) { balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice())) pool.currentState.AddBalance(from, balance) - if err := pool.AddRemote(tx); err != ErrIntrinsicGas { + if err := pool.AddRemote(tx); !errors.Is(err, ErrIntrinsicGas) { t.Error("expected", ErrIntrinsicGas, "got", err) } diff --git a/eth/api_backend.go b/eth/api_backend.go index b6d727076..60ad37e68 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -289,7 +289,7 @@ func (b *EthAPIBackend) ExtRPCEnabled() bool { return b.extRPCEnabled } -func (b *EthAPIBackend) RPCGasCap() *big.Int { +func (b *EthAPIBackend) RPCGasCap() uint64 { return b.eth.config.RPCGasCap } diff --git a/eth/config.go b/eth/config.go index 84a2f140a..53acec6c3 100644 --- a/eth/config.go +++ b/eth/config.go @@ -59,7 +59,8 @@ var DefaultConfig = Config{ GasPrice: big.NewInt(params.GWei), Recommit: 3 * time.Second, }, - TxPool: core.DefaultTxPoolConfig, + TxPool: core.DefaultTxPoolConfig, + RPCGasCap: 25000000, GPO: gasprice.Config{ Blocks: 20, Percentile: 60, @@ -158,7 +159,7 @@ type Config struct { EVMInterpreter string // RPCGasCap is the global gas cap for eth-call variants. - RPCGasCap *big.Int `toml:",omitempty"` + RPCGasCap uint64 `toml:",omitempty"` // RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for // send-transction variants. The unit is ether. diff --git a/eth/gen_config.go b/eth/gen_config.go index f3d189185..8f4a8fa94 100644 --- a/eth/gen_config.go +++ b/eth/gen_config.go @@ -3,7 +3,6 @@ package eth import ( - "math/big" "time" "github.com/ethereum/go-ethereum/common" @@ -49,7 +48,7 @@ func (c Config) MarshalTOML() (interface{}, error) { DocRoot string `toml:"-"` EWASMInterpreter string EVMInterpreter string - RPCGasCap *big.Int `toml:",omitempty"` + RPCGasCap uint64 `toml:",omitempty"` RPCTxFeeCap float64 `toml:",omitempty"` Checkpoint *params.TrustedCheckpoint `toml:",omitempty"` CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"` @@ -127,7 +126,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { DocRoot *string `toml:"-"` EWASMInterpreter *string EVMInterpreter *string - RPCGasCap *big.Int `toml:",omitempty"` + RPCGasCap *uint64 `toml:",omitempty"` RPCTxFeeCap *float64 `toml:",omitempty"` Checkpoint *params.TrustedCheckpoint `toml:",omitempty"` CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"` @@ -230,7 +229,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { c.EVMInterpreter = *dec.EVMInterpreter } if dec.RPCGasCap != nil { - c.RPCGasCap = dec.RPCGasCap + c.RPCGasCap = *dec.RPCGasCap } if dec.RPCTxFeeCap != nil { c.RPCTxFeeCap = *dec.RPCTxFeeCap diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index f26691710..1e01c4167 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -741,7 +741,7 @@ type CallArgs struct { } // ToMessage converts CallArgs to the Message type used by the core evm -func (args *CallArgs) ToMessage(globalGasCap *big.Int) types.Message { +func (args *CallArgs) ToMessage(globalGasCap uint64) types.Message { // Set sender address or use zero address if none specified. var addr common.Address if args.From != nil { @@ -753,9 +753,9 @@ func (args *CallArgs) ToMessage(globalGasCap *big.Int) types.Message { if args.Gas != nil { gas = uint64(*args.Gas) } - if globalGasCap != nil && globalGasCap.Uint64() < gas { + if globalGasCap != 0 && globalGasCap < gas { log.Warn("Caller gas above allowance, capping", "requested", gas, "cap", globalGasCap) - gas = globalGasCap.Uint64() + gas = globalGasCap } gasPrice := new(big.Int) if args.GasPrice != nil { @@ -790,7 +790,7 @@ type account struct { StateDiff *map[common.Hash]common.Hash `json:"stateDiff"` } -func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides map[common.Address]account, vmCfg vm.Config, timeout time.Duration, globalGasCap *big.Int) (*core.ExecutionResult, error) { +func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides map[common.Address]account, vmCfg vm.Config, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) { defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) @@ -861,7 +861,10 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo if evm.Cancelled() { return nil, fmt.Errorf("execution aborted (timeout = %v)", timeout) } - return result, err + if err != nil { + return result, fmt.Errorf("err: %w (supplied gas %d)", err, msg.Gas()) + } + return result, nil } func newRevertError(result *core.ExecutionResult) *revertError { @@ -916,7 +919,7 @@ func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNrOr return result.Return(), result.Err } -func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, gasCap *big.Int) (hexutil.Uint64, error) { +func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, gasCap uint64) (hexutil.Uint64, error) { // Binary search the gas requirement, as it may be higher than the amount used var ( lo uint64 = params.TxGas - 1 @@ -964,9 +967,9 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNrOrHash } } // Recap the highest gas allowance with specified gascap. - if gasCap != nil && hi > gasCap.Uint64() { + if gasCap != 0 && hi > gasCap { log.Warn("Caller gas above allowance, capping", "requested", hi, "cap", gasCap) - hi = gasCap.Uint64() + hi = gasCap } cap = hi @@ -976,7 +979,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNrOrHash result, err := DoCall(ctx, b, args, blockNrOrHash, nil, vm.Config{}, 0, gasCap) if err != nil { - if err == core.ErrIntrinsicGas { + if errors.Is(err, core.ErrIntrinsicGas) { return true, nil, nil // Special case, raise gas limit } return true, nil, err // Bail out diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 5f5f9a6ee..dbdd35ac7 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -45,8 +45,8 @@ type Backend interface { ChainDb() ethdb.Database AccountManager() *accounts.Manager ExtRPCEnabled() bool - RPCGasCap() *big.Int // global gas cap for eth_call over rpc: DoS protection RPCTxFeeCap() float64 // global tx fee cap for all transaction related APIs + RPCGasCap() uint64 // global gas cap for eth_call over rpc: DoS protection // Blockchain API SetHead(number uint64) diff --git a/les/api_backend.go b/les/api_backend.go index 75f255cd9..f72cbba07 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -258,7 +258,7 @@ func (b *LesApiBackend) ExtRPCEnabled() bool { return b.extRPCEnabled } -func (b *LesApiBackend) RPCGasCap() *big.Int { +func (b *LesApiBackend) RPCGasCap() uint64 { return b.eth.config.RPCGasCap }