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:
Péter Szilágyi 2018-03-05 14:23:48 +02:00 committed by GitHub
commit 223fe3f26e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 14 additions and 25 deletions

View File

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

View File

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

View File

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

View File

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