Merge pull request #16229 from karalabe/evm-call-fix
cmd/evm, core/vm, internal/ethapi: don't disable call gas metering
This commit is contained in:
commit
223fe3f26e
@ -86,10 +86,6 @@ var (
|
|||||||
Name: "create",
|
Name: "create",
|
||||||
Usage: "indicates the action should be create rather than call",
|
Usage: "indicates the action should be create rather than call",
|
||||||
}
|
}
|
||||||
DisableGasMeteringFlag = cli.BoolFlag{
|
|
||||||
Name: "nogasmetering",
|
|
||||||
Usage: "disable gas metering",
|
|
||||||
}
|
|
||||||
GenesisFlag = cli.StringFlag{
|
GenesisFlag = cli.StringFlag{
|
||||||
Name: "prestate",
|
Name: "prestate",
|
||||||
Usage: "JSON file with prestate (genesis) config",
|
Usage: "JSON file with prestate (genesis) config",
|
||||||
@ -128,7 +124,6 @@ func init() {
|
|||||||
ValueFlag,
|
ValueFlag,
|
||||||
DumpFlag,
|
DumpFlag,
|
||||||
InputFlag,
|
InputFlag,
|
||||||
DisableGasMeteringFlag,
|
|
||||||
MemProfileFlag,
|
MemProfileFlag,
|
||||||
CPUProfileFlag,
|
CPUProfileFlag,
|
||||||
StatDumpFlag,
|
StatDumpFlag,
|
||||||
|
@ -161,9 +161,8 @@ func runCmd(ctx *cli.Context) error {
|
|||||||
GasPrice: utils.GlobalBig(ctx, PriceFlag.Name),
|
GasPrice: utils.GlobalBig(ctx, PriceFlag.Name),
|
||||||
Value: utils.GlobalBig(ctx, ValueFlag.Name),
|
Value: utils.GlobalBig(ctx, ValueFlag.Name),
|
||||||
EVMConfig: vm.Config{
|
EVMConfig: vm.Config{
|
||||||
Tracer: tracer,
|
Tracer: tracer,
|
||||||
Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name),
|
Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name),
|
||||||
DisableGasMetering: ctx.GlobalBool(DisableGasMeteringFlag.Name),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,8 +37,6 @@ type Config struct {
|
|||||||
// NoRecursion disabled Interpreter call, callcode,
|
// NoRecursion disabled Interpreter call, callcode,
|
||||||
// delegate call and create.
|
// delegate call and create.
|
||||||
NoRecursion bool
|
NoRecursion bool
|
||||||
// Disable gas metering
|
|
||||||
DisableGasMetering bool
|
|
||||||
// Enable recording of SHA3/keccak preimages
|
// Enable recording of SHA3/keccak preimages
|
||||||
EnablePreimageRecording bool
|
EnablePreimageRecording bool
|
||||||
// JumpTable contains the EVM instruction table. This
|
// JumpTable contains the EVM instruction table. This
|
||||||
@ -189,14 +187,11 @@ func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err er
|
|||||||
return nil, errGasUintOverflow
|
return nil, errGasUintOverflow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// consume the gas and return an error if not enough gas is available.
|
||||||
if !in.cfg.DisableGasMetering {
|
// cost is explicitly set so that the capture state defer method cas get the proper cost
|
||||||
// consume the gas and return an error if not enough gas is available.
|
cost, err = operation.gasCost(in.gasTable, in.evm, contract, stack, mem, memorySize)
|
||||||
// cost is explicitly set so that the capture state defer method cas get the proper cost
|
if err != nil || !contract.UseGas(cost) {
|
||||||
cost, err = operation.gasCost(in.gasTable, in.evm, contract, stack, mem, memorySize)
|
return nil, ErrOutOfGas
|
||||||
if err != nil || !contract.UseGas(cost) {
|
|
||||||
return nil, ErrOutOfGas
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if memorySize > 0 {
|
if memorySize > 0 {
|
||||||
mem.Resize(memorySize)
|
mem.Resize(memorySize)
|
||||||
|
@ -611,7 +611,7 @@ type CallArgs struct {
|
|||||||
Data hexutil.Bytes `json:"data"`
|
Data hexutil.Bytes `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config) ([]byte, uint64, bool, error) {
|
func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config, timeout time.Duration) ([]byte, uint64, bool, error) {
|
||||||
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
|
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
|
||||||
|
|
||||||
state, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
|
state, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
|
||||||
@ -630,7 +630,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
|
|||||||
// Set default gas & gas price if none were set
|
// Set default gas & gas price if none were set
|
||||||
gas, gasPrice := uint64(args.Gas), args.GasPrice.ToInt()
|
gas, gasPrice := uint64(args.Gas), args.GasPrice.ToInt()
|
||||||
if gas == 0 {
|
if gas == 0 {
|
||||||
gas = 50000000
|
gas = math.MaxUint64 / 2
|
||||||
}
|
}
|
||||||
if gasPrice.Sign() == 0 {
|
if gasPrice.Sign() == 0 {
|
||||||
gasPrice = new(big.Int).SetUint64(defaultGasPrice)
|
gasPrice = new(big.Int).SetUint64(defaultGasPrice)
|
||||||
@ -642,14 +642,14 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
|
|||||||
// Setup context so it may be cancelled the call has completed
|
// Setup context so it may be cancelled the call has completed
|
||||||
// or, in case of unmetered gas, setup a context with a timeout.
|
// or, in case of unmetered gas, setup a context with a timeout.
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
if vmCfg.DisableGasMetering {
|
if timeout > 0 {
|
||||||
ctx, cancel = context.WithTimeout(ctx, time.Second*5)
|
ctx, cancel = context.WithTimeout(ctx, timeout)
|
||||||
} else {
|
} else {
|
||||||
ctx, cancel = context.WithCancel(ctx)
|
ctx, cancel = context.WithCancel(ctx)
|
||||||
}
|
}
|
||||||
// Make sure the context is cancelled when the call has completed
|
// Make sure the context is cancelled when the call has completed
|
||||||
// this makes sure resources are cleaned up.
|
// this makes sure resources are cleaned up.
|
||||||
defer func() { cancel() }()
|
defer cancel()
|
||||||
|
|
||||||
// Get a new instance of the EVM.
|
// Get a new instance of the EVM.
|
||||||
evm, vmError, err := s.b.GetEVM(ctx, msg, state, header, vmCfg)
|
evm, vmError, err := s.b.GetEVM(ctx, msg, state, header, vmCfg)
|
||||||
@ -676,7 +676,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
|
|||||||
// Call executes the given transaction on the state for the given block number.
|
// 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.
|
// 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) {
|
func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (hexutil.Bytes, error) {
|
||||||
result, _, _, err := s.doCall(ctx, args, blockNr, vm.Config{DisableGasMetering: true})
|
result, _, _, err := s.doCall(ctx, args, blockNr, vm.Config{}, 5*time.Second)
|
||||||
return (hexutil.Bytes)(result), err
|
return (hexutil.Bytes)(result), err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -705,7 +705,7 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (h
|
|||||||
executable := func(gas uint64) bool {
|
executable := func(gas uint64) bool {
|
||||||
args.Gas = hexutil.Uint64(gas)
|
args.Gas = hexutil.Uint64(gas)
|
||||||
|
|
||||||
_, _, failed, err := s.doCall(ctx, args, rpc.PendingBlockNumber, vm.Config{})
|
_, _, failed, err := s.doCall(ctx, args, rpc.PendingBlockNumber, vm.Config{}, 0)
|
||||||
if err != nil || failed {
|
if err != nil || failed {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user