rpc, internal/ethapi: default rpc gascap at 25M + better error message (#21229)

* rpc, internal/ethapi: default rpc gascap at 50M + better error message

* eth,internal: make globalgascap uint64

* core/tests: fix compilation failure

* eth/config: gascap at 25M + minor review concerns
This commit is contained in:
Martin Holst Swende 2020-07-01 19:54:21 +02:00 committed by GitHub
parent af5c97aebe
commit 12867d152c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 31 additions and 21 deletions

View File

@ -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)

View File

@ -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)
}

View File

@ -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
}

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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
}