From 22ca13fa85de18093b87d924b58df9ce072077ba Mon Sep 17 00:00:00 2001 From: Jeffrey Wilcke Date: Mon, 13 Mar 2017 21:45:05 +0100 Subject: [PATCH] core/vm: renamed variables --- core/vm/evm.go | 3 ++ core/vm/interpreter.go | 76 +++++++++++++++++++++++------------------- params/config.go | 6 +++- 3 files changed, 50 insertions(+), 35 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 09197e14fe..8c8322bd16 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -91,6 +91,8 @@ type EVM struct { // chainConfig contains information about the current chain chainConfig *params.ChainConfig + // chain rules contains the chain rules for the current epoch + chainRules params.Rules // virtual machine configuration options used to initialise the // evm. vmConfig Config @@ -110,6 +112,7 @@ func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmCon StateDB: statedb, vmConfig: vmConfig, chainConfig: chainConfig, + chainRules: chainConfig.Rules(ctx.BlockNumber), } evm.interpreter = NewInterpreter(evm, vmConfig) diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index f571744739..1614838cb5 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -46,18 +46,18 @@ type Config struct { DisableGasMetering bool // Enable recording of SHA3/keccak preimages EnablePreimageRecording bool - // JumpTable contains the EVM instruction table. This + // JumpTable contains the in instruction table. This // may me left uninitialised and will be set the default // table. JumpTable [256]operation } // Interpreter is used to run Ethereum based contracts and will utilise the -// passed environment to query external sources for state information. +// passed evmironment to query external sources for state information. // The Interpreter will run the byte code VM or JIT VM based on the passed // configuration. type Interpreter struct { - env *EVM + evm *EVM cfg Config gasTable params.GasTable intPool *intPool @@ -66,15 +66,15 @@ type Interpreter struct { } // NewInterpreter returns a new instance of the Interpreter. -func NewInterpreter(env *EVM, cfg Config) *Interpreter { +func NewInterpreter(evm *EVM, cfg Config) *Interpreter { // We use the STOP instruction whether to see // the jump table was initialised. If it was not // we'll set the default jump table. if !cfg.JumpTable[STOP].valid { switch { - case env.ChainConfig().IsMetropolis(env.BlockNumber): + case evm.ChainConfig().IsMetropolis(evm.BlockNumber): cfg.JumpTable = metropolisInstructionSet - case env.ChainConfig().IsHomestead(env.BlockNumber): + case evm.ChainConfig().IsHomestead(evm.BlockNumber): cfg.JumpTable = homesteadInstructionSet default: cfg.JumpTable = baseInstructionSet @@ -82,22 +82,36 @@ func NewInterpreter(env *EVM, cfg Config) *Interpreter { } return &Interpreter{ - env: env, + evm: evm, cfg: cfg, - gasTable: env.ChainConfig().GasTable(env.BlockNumber), + gasTable: evm.ChainConfig().GasTable(evm.BlockNumber), intPool: newIntPool(), } } +func (in *Interpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error { + if in.evm.chainRules.IsMetropolis { + if in.readonly { + // if the interpreter is operating in readonly mode, make sure no + // state-modifying operation is performed. + if operation.writes || + ((op == CALL || op == CALLCODE) && stack.Back(3).BitLen() > 0) { + return errWriteProtection + } + } + } + return nil +} + // Run loops and evaluates the contract's code with the given input data and returns // the return byte-slice and an error if one occured. // // It's important to note that any errors returned by the interpreter should be // considered a revert-and-consume-all-gas operation. No error specific checks -// should be handled to reduce complexity and errors further down the EVM. -func (evm *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret []byte, err error) { - evm.env.depth++ - defer func() { evm.env.depth-- }() +// should be handled to reduce complexity and errors further down the in. +func (in *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret []byte, err error) { + in.evm.depth++ + defer func() { in.evm.depth-- }() // Don't bother with the execution if there's no code. if len(contract.Code) == 0 { @@ -123,37 +137,31 @@ func (evm *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret // User defer pattern to check for an error and, based on the error being nil or not, use all gas and return. defer func() { - if err != nil && evm.cfg.Debug { + if err != nil && in.cfg.Debug { // XXX For debugging //fmt.Printf("%04d: %8v cost = %-8d stack = %-8d ERR = %v\n", pc, op, cost, stack.len(), err) // TODO update the tracer to accept uint64 instead of *big.Int g, c := new(big.Int).SetUint64(contract.Gas), new(big.Int).SetUint64(cost) - evm.cfg.Tracer.CaptureState(evm.env, pc, op, contract.Gas, cost, mem, stack, contract, evm.env.depth, err) + in.cfg.Tracer.CaptureState(in.evm, pc, op, g, c, mem, stack, contract, in.evm.depth, err) } }() - log.Debug("EVM running contract", "hash", codehash[:]) + log.Debug("in running contract", "hash", codehash[:]) tstart := time.Now() - defer log.Debug("EVM finished running contract", "hash", codehash[:], "elapsed", time.Since(tstart)) + defer log.Debug("in finished running contract", "hash", codehash[:], "elapsed", time.Since(tstart)) // The Interpreter main run loop (contextual). This loop runs until either an // explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during - // the execution of one of the operations or until the evm.done is set by + // the execution of one of the operations or until the in.done is set by // the parent context.Context. - for atomic.LoadInt32(&evm.env.abort) == 0 { + for atomic.LoadInt32(&in.evm.abort) == 0 { // Get the memory location of pc op = contract.GetOp(pc) // get the operation from the jump table matching the opcode - operation := evm.cfg.JumpTable[op] - // if the interpreter is operating in readonly mode, make sure no - // state-modifying operation is performed. - if evm.readonly && evm.env.chainConfig.IsMetropolis(evm.env.BlockNumber) { - if operation.writes || - ((op == CALL || op == CALLCODE) && stack.Back(3).BitLen() > 0) { - return nil, errWriteProtection - } - + operation := in.cfg.JumpTable[op] + if err := in.enforceRestrictions(op, operation, stack); err != nil { + return nil, err } // if the op is invalid abort the process and return an error @@ -182,10 +190,10 @@ func (evm *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret } } - if !evm.cfg.DisableGasMetering { + if !in.cfg.DisableGasMetering { // consume the gas and return an error if not enough gas is available. // cost is explicitly set so that the capture state defer method cas get the proper cost - cost, err = operation.gasCost(evm.gasTable, evm.env, contract, stack, mem, memorySize) + cost, err = operation.gasCost(in.gasTable, in.evm, contract, stack, mem, memorySize) if err != nil || !contract.UseGas(cost) { return nil, ErrOutOfGas } @@ -194,25 +202,25 @@ func (evm *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret mem.Resize(memorySize) } - if evm.cfg.Debug { + if in.cfg.Debug { // TODO update the tracer to accept uint64 instead of *big.Int g, c := new(big.Int).SetUint64(contract.Gas), new(big.Int).SetUint64(cost) - evm.cfg.Tracer.CaptureState(evm.env, pc, op, g, c, mem, stack, contract, evm.env.depth, err) + in.cfg.Tracer.CaptureState(in.evm, pc, op, g, c, mem, stack, contract, in.evm.depth, err) } // XXX For debugging //fmt.Printf("%04d: %8v cost = %-8d stack = %-8d\n", pc, op, cost, stack.len()) // execute the operation - res, err := operation.execute(&pc, evm.env, contract, mem, stack) + res, err := operation.execute(&pc, in.evm, contract, mem, stack) // verifyPool is a build flag. Pool verification makes sure the integrity // of the integer pool by comparing values to a default value. if verifyPool { - verifyIntegerPool(evm.intPool) + verifyIntegerPool(in.intPool) } // checks whether the operation should revert state. if operation.reverts { - evm.env.StateDB.RevertToSnapshot(snapshot) + in.evm.StateDB.RevertToSnapshot(snapshot) } switch { diff --git a/params/config.go b/params/config.go index b29371960d..be00b9f1f8 100644 --- a/params/config.go +++ b/params/config.go @@ -255,5 +255,9 @@ type Rules struct { } func (c *ChainConfig) Rules(num *big.Int) Rules { - return Rules{ChainId: new(big.Int).Set(c.ChainId), IsHomestead: c.IsHomestead(num), IsEIP150: c.IsEIP150(num), IsEIP155: c.IsEIP155(num), IsEIP158: c.IsEIP158(num), IsMetropolis: c.IsMetropolis(num)} + chainId := c.ChainId + if chainId == nil { + chainId = new(big.Int) + } + return Rules{ChainId: new(big.Int).Set(chainId), IsHomestead: c.IsHomestead(num), IsEIP150: c.IsEIP150(num), IsEIP155: c.IsEIP155(num), IsEIP158: c.IsEIP158(num), IsMetropolis: c.IsMetropolis(num)} }