From 807044be87b0ea455dfe152ce2cecaa58ac8a4e8 Mon Sep 17 00:00:00 2001 From: cdetrio Date: Thu, 24 Aug 2017 12:31:38 -0400 Subject: [PATCH] cmd/evm, core/vm/runtime: add more support for prestate configs --- cmd/evm/runner.go | 33 +++++++++++++++++++++++++++++++-- core/vm/runtime/env.go | 3 +-- core/vm/runtime/runtime.go | 7 +++++-- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index 96de0c76ac..d945cbae15 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -24,6 +24,7 @@ import ( "os" "runtime/pprof" "time" + "math/big" goruntime "runtime" @@ -83,6 +84,10 @@ func runCmd(ctx *cli.Context) error { debugLogger *vm.StructLogger statedb *state.StateDB chainConfig *params.ChainConfig + genCoinbase common.Address + genTimestamp uint64 + genGasLimit uint64 + genDifficulty *big.Int sender = common.StringToAddress("sender") receiver = common.StringToAddress("receiver") ) @@ -96,6 +101,10 @@ func runCmd(ctx *cli.Context) error { } if ctx.GlobalString(GenesisFlag.Name) != "" { gen := readGenesis(ctx.GlobalString(GenesisFlag.Name)) + genCoinbase = gen.Coinbase + genDifficulty = gen.Difficulty + genGasLimit = gen.GasLimit + genTimestamp = gen.Timestamp _, statedb = gen.ToBlock() chainConfig = gen.Config } else { @@ -105,7 +114,8 @@ func runCmd(ctx *cli.Context) error { if ctx.GlobalString(SenderFlag.Name) != "" { sender = common.HexToAddress(ctx.GlobalString(SenderFlag.Name)) } - statedb.CreateAccount(sender) + // TODO: createAccount overwrites the nonce in the prestate. should only be used if no prestate provided + // statedb.CreateAccount(sender) if ctx.GlobalString(ReceiverFlag.Name) != "" { receiver = common.HexToAddress(ctx.GlobalString(ReceiverFlag.Name)) @@ -154,9 +164,13 @@ func runCmd(ctx *cli.Context) error { initialGas := ctx.GlobalUint64(GasFlag.Name) runtimeConfig := runtime.Config{ Origin: sender, + Time: new(big.Int).SetUint64(genTimestamp), + Coinbase: genCoinbase, + Difficulty: genDifficulty, State: statedb, - GasLimit: initialGas, + GasLimit: genGasLimit, GasPrice: utils.GlobalBig(ctx, PriceFlag.Name), + TxGasLimit: initialGas, Value: utils.GlobalBig(ctx, ValueFlag.Name), EVMConfig: vm.Config{ Tracer: tracer, @@ -183,15 +197,30 @@ func runCmd(ctx *cli.Context) error { } tstart := time.Now() var leftOverGas uint64 + + // sender account pre-pays gas + mgval := new(big.Int).Mul(new(big.Int).SetUint64(initialGas), runtimeConfig.GasPrice) + statedb.SubBalance(sender, mgval) + if ctx.GlobalBool(CreateFlag.Name) { input := append(code, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name))...) + intrinsicGas := core.IntrinsicGas(input, ctx.GlobalBool(CreateFlag.Name), true) + initialGas -= intrinsicGas.Uint64() + runtimeConfig.TxGasLimit = initialGas ret, _, leftOverGas, err = runtime.Create(input, &runtimeConfig) } else { if len(code) > 0 { statedb.SetCode(receiver, code) } + intrinsicGas := core.IntrinsicGas(common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), false, true) + initialGas -= intrinsicGas.Uint64() + runtimeConfig.TxGasLimit = initialGas ret, leftOverGas, err = runtime.Call(receiver, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtimeConfig) } + // refund sender unused prepaid gas + remainingEther := new(big.Int).Mul(new(big.Int).SetUint64(leftOverGas), runtimeConfig.GasPrice) + statedb.AddBalance(sender, remainingEther) + execTime := time.Since(tstart) if ctx.GlobalBool(DumpFlag.Name) { diff --git a/core/vm/runtime/env.go b/core/vm/runtime/env.go index 818da1be26..97ea3b17a3 100644 --- a/core/vm/runtime/env.go +++ b/core/vm/runtime/env.go @@ -19,7 +19,6 @@ package runtime import ( "math/big" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/vm" ) @@ -28,7 +27,7 @@ func NewEnv(cfg *Config) *vm.EVM { context := vm.Context{ CanTransfer: core.CanTransfer, Transfer: core.Transfer, - GetHash: func(uint64) common.Hash { return common.Hash{} }, + GetHash: cfg.GetHashFn, Origin: cfg.Origin, Coinbase: cfg.Coinbase, diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index edbf541766..17bcebe18b 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -40,6 +40,7 @@ type Config struct { Time *big.Int GasLimit uint64 GasPrice *big.Int + TxGasLimit uint64 Value *big.Int DisableJit bool // "disable" so it's enabled by default Debug bool @@ -95,6 +96,8 @@ func setDefaults(cfg *Config) { // the given code. It enabled the JIT by default and make sure that it's restored // to it's original state afterwards. func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { + // TODO: remove Execute()? + // only used in runtime_example_test.go if cfg == nil { cfg = new(Config) } @@ -144,7 +147,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { code, address, leftOverGas, err := vmenv.Create( sender, input, - cfg.GasLimit, + cfg.TxGasLimit, cfg.Value, ) return code, address, leftOverGas, err @@ -166,7 +169,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er sender, address, input, - cfg.GasLimit, + cfg.TxGasLimit, cfg.Value, )