From 21ac4dd1091b3c11e9344ae8f607f19788667e92 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Sun, 4 Jun 2017 20:46:29 +0200 Subject: [PATCH] core/vm, cmd/evm: Add ability for 'evm' binary to report gas used --- cmd/evm/runner.go | 14 ++++++++------ core/vm/runtime/runtime.go | 12 ++++++------ core/vm/runtime/runtime_test.go | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index a9e032b1a9..c1e731e23d 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -137,11 +137,11 @@ func runCmd(ctx *cli.Context) error { } code = common.Hex2Bytes(string(bytes.TrimRight(hexcode, "\n"))) } - + initialGas := ctx.GlobalUint64(GasFlag.Name) runtimeConfig := runtime.Config{ Origin: sender, State: statedb, - GasLimit: ctx.GlobalUint64(GasFlag.Name), + GasLimit: initialGas, GasPrice: utils.GlobalBig(ctx, PriceFlag.Name), Value: utils.GlobalBig(ctx, ValueFlag.Name), EVMConfig: vm.Config{ @@ -168,14 +168,15 @@ func runCmd(ctx *cli.Context) error { runtimeConfig.ChainConfig = chainConfig } tstart := time.Now() + var leftOverGas uint64 if ctx.GlobalBool(CreateFlag.Name) { input := append(code, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name))...) - ret, _, err = runtime.Create(input, &runtimeConfig) + ret, _, leftOverGas, err = runtime.Create(input, &runtimeConfig) } else { receiver := common.StringToAddress("receiver") statedb.SetCode(receiver, code) - ret, err = runtime.Call(receiver, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtimeConfig) + ret, leftOverGas, err = runtime.Call(receiver, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtimeConfig) } execTime := time.Since(tstart) @@ -214,11 +215,12 @@ heap objects: %d allocations: %d total allocations: %d GC calls: %d +Gas used: %d -`, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC) +`, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC, initialGas-leftOverGas) } if tracer != nil { - tracer.CaptureEnd(ret, 0, execTime) + tracer.CaptureEnd(ret, initialGas-leftOverGas, execTime) } else { fmt.Printf("0x%x\n", ret) } diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 94265626f2..aa386a995e 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -125,7 +125,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { } // Create executes the code using the EVM create method -func Create(input []byte, cfg *Config) ([]byte, common.Address, error) { +func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { if cfg == nil { cfg = new(Config) } @@ -141,13 +141,13 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, error) { ) // Call the code with the given configuration. - code, address, _, err := vmenv.Create( + code, address, leftOverGas, err := vmenv.Create( sender, input, cfg.GasLimit, cfg.Value, ) - return code, address, err + return code, address, leftOverGas, err } // Call executes the code given by the contract's address. It will return the @@ -155,14 +155,14 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, error) { // // Call, unlike Execute, requires a config and also requires the State field to // be set. -func Call(address common.Address, input []byte, cfg *Config) ([]byte, error) { +func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, error) { setDefaults(cfg) vmenv := NewEnv(cfg, cfg.State) sender := cfg.State.GetOrNewStateObject(cfg.Origin) // Call the code with the given configuration. - ret, _, err := vmenv.Call( + ret, leftOverGas, err := vmenv.Call( sender, address, input, @@ -170,5 +170,5 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, error) { cfg.Value, ) - return ret, err + return ret, leftOverGas, err } diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go index fe39e97a01..7f40770d21 100644 --- a/core/vm/runtime/runtime_test.go +++ b/core/vm/runtime/runtime_test.go @@ -106,7 +106,7 @@ func TestCall(t *testing.T) { byte(vm.RETURN), }) - ret, err := Call(address, nil, &Config{State: state}) + ret, _, err := Call(address, nil, &Config{State: state}) if err != nil { t.Fatal("didn't expect error", err) }