mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
graphql, ethapi: place gas cap in DoCall
This commit is contained in:
parent
9e93063e16
commit
0c3563eb36
2 changed files with 18 additions and 31 deletions
|
|
@ -856,7 +856,7 @@ func (b *Block) Call(ctx context.Context, args struct {
|
|||
}
|
||||
}
|
||||
|
||||
result, gas, failed, err := ethapi.DoCall(ctx, b.backend, args.Data, *b.num, vm.Config{}, 5*time.Second)
|
||||
result, gas, failed, err := ethapi.DoCall(ctx, b.backend, args.Data, *b.num, vm.Config{}, 5*time.Second, b.backend.RPCGasCap())
|
||||
status := hexutil.Uint64(1)
|
||||
if failed {
|
||||
status = 0
|
||||
|
|
@ -883,7 +883,7 @@ func (b *Block) EstimateGas(ctx context.Context, args struct {
|
|||
}
|
||||
}
|
||||
|
||||
gas, err := ethapi.DoEstimateGas(ctx, b.backend, args.Data, *b.num)
|
||||
gas, err := ethapi.DoEstimateGas(ctx, b.backend, args.Data, *b.num, b.backend.RPCGasCap())
|
||||
return gas, err
|
||||
}
|
||||
|
||||
|
|
@ -927,7 +927,7 @@ func (p *Pending) Account(ctx context.Context, args struct {
|
|||
func (p *Pending) Call(ctx context.Context, args struct {
|
||||
Data ethapi.CallArgs
|
||||
}) (*CallResult, error) {
|
||||
result, gas, failed, err := ethapi.DoCall(ctx, p.backend, args.Data, rpc.PendingBlockNumber, vm.Config{}, 5*time.Second)
|
||||
result, gas, failed, err := ethapi.DoCall(ctx, p.backend, args.Data, rpc.PendingBlockNumber, vm.Config{}, 5*time.Second, p.backend.RPCGasCap())
|
||||
status := hexutil.Uint64(1)
|
||||
if failed {
|
||||
status = 0
|
||||
|
|
@ -942,7 +942,7 @@ func (p *Pending) Call(ctx context.Context, args struct {
|
|||
func (p *Pending) EstimateGas(ctx context.Context, args struct {
|
||||
Data ethapi.CallArgs
|
||||
}) (hexutil.Uint64, error) {
|
||||
return ethapi.DoEstimateGas(ctx, p.backend, args.Data, rpc.PendingBlockNumber)
|
||||
return ethapi.DoEstimateGas(ctx, p.backend, args.Data, rpc.PendingBlockNumber, p.backend.RPCGasCap())
|
||||
}
|
||||
|
||||
// Resolver is the top-level object in the GraphQL hierarchy.
|
||||
|
|
|
|||
|
|
@ -674,7 +674,7 @@ type CallArgs struct {
|
|||
Data *hexutil.Bytes `json:"data"`
|
||||
}
|
||||
|
||||
func DoCall(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config, timeout time.Duration) ([]byte, uint64, bool, error) {
|
||||
func DoCall(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config, timeout time.Duration, globalGasCap *big.Int) ([]byte, uint64, bool, error) {
|
||||
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
|
||||
|
||||
state, header, err := b.StateAndHeaderByNumber(ctx, blockNr)
|
||||
|
|
@ -697,6 +697,10 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumb
|
|||
if args.Gas != nil {
|
||||
gas = uint64(*args.Gas)
|
||||
}
|
||||
if globalGasCap != nil && globalGasCap.Uint64() < gas {
|
||||
log.Warn("Applying cap on gas, caller requested amount above limit", "cap", globalGasCap, "attempted", gas)
|
||||
gas = globalGasCap.Uint64()
|
||||
}
|
||||
gasPrice := new(big.Int).SetUint64(defaultGasPrice)
|
||||
if args.GasPrice != nil {
|
||||
gasPrice = args.GasPrice.ToInt()
|
||||
|
|
@ -752,25 +756,11 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumb
|
|||
// Call executes the given transaction on the state for the given block number.
|
||||
// It doesn't make and changes in the state/blockchain and is useful to execute and retrieve values.
|
||||
func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (hexutil.Bytes, error) {
|
||||
if gasCap := s.b.RPCGasCap(); gasCap != nil {
|
||||
if new(big.Int).SetUint64(uint64(*args.Gas)).Cmp(gasCap) > 0 {
|
||||
log.Warn("Applying cap on gas, caller requested amount above limit", "cap", gasCap, "requested", args.Gas)
|
||||
newGas := hexutil.Uint64(gasCap.Uint64())
|
||||
*args.Gas = newGas
|
||||
}
|
||||
result, _, _, err := DoCall(ctx, s.b, args, blockNr, vm.Config{}, 5*time.Second)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("%v (gas capped at: %d)", err, *args.Gas)
|
||||
}
|
||||
return (hexutil.Bytes)(result), err
|
||||
} else {
|
||||
result, _, _, err := DoCall(ctx, s.b, args, blockNr, vm.Config{}, 5*time.Second)
|
||||
return (hexutil.Bytes)(result), err
|
||||
}
|
||||
|
||||
result, _, _, err := DoCall(ctx, s.b, args, blockNr, vm.Config{}, 5*time.Second, s.b.RPCGasCap())
|
||||
return (hexutil.Bytes)(result), err
|
||||
}
|
||||
|
||||
func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumber) (hexutil.Uint64, error) {
|
||||
func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.BlockNumber, gasCap *big.Int) (hexutil.Uint64, error) {
|
||||
// Binary search the gas requirement, as it may be higher than the amount used
|
||||
var (
|
||||
lo uint64 = params.TxGas - 1
|
||||
|
|
@ -787,13 +777,17 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.Bl
|
|||
}
|
||||
hi = block.GasLimit()
|
||||
}
|
||||
if gasCap != nil && hi > gasCap.Uint64() {
|
||||
log.Warn("Applying cap on gas, caller requested amount above limit", "cap", gasCap, "attempted", hi)
|
||||
hi = gasCap.Uint64()
|
||||
}
|
||||
cap = hi
|
||||
|
||||
// Create a helper to check if a gas allowance results in an executable transaction
|
||||
executable := func(gas uint64) bool {
|
||||
args.Gas = (*hexutil.Uint64)(&gas)
|
||||
|
||||
_, _, failed, err := DoCall(ctx, b, args, rpc.PendingBlockNumber, vm.Config{}, 0)
|
||||
_, _, failed, err := DoCall(ctx, b, args, rpc.PendingBlockNumber, vm.Config{}, 0, gasCap)
|
||||
if err != nil || failed {
|
||||
return false
|
||||
}
|
||||
|
|
@ -820,14 +814,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNr rpc.Bl
|
|||
// EstimateGas returns an estimate of the amount of gas needed to execute the
|
||||
// given transaction against the current pending block.
|
||||
func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (hexutil.Uint64, error) {
|
||||
if gasCap := s.b.RPCGasCap(); gasCap != nil {
|
||||
if new(big.Int).SetUint64(uint64(*args.Gas)).Cmp(gasCap) > 0 {
|
||||
log.Warn("Applying cap on gas, caller requested amount above limit", "cap", gasCap, "requested", args.Gas)
|
||||
newGas := hexutil.Uint64(gasCap.Uint64())
|
||||
*args.Gas = newGas
|
||||
}
|
||||
}
|
||||
return DoEstimateGas(ctx, s.b, args, rpc.PendingBlockNumber)
|
||||
return DoEstimateGas(ctx, s.b, args, rpc.PendingBlockNumber, s.b.RPCGasCap())
|
||||
}
|
||||
|
||||
// ExecutionResult groups all structured logs emitted by the EVM
|
||||
|
|
|
|||
Loading…
Reference in a new issue