core/vm: renamed variables

This commit is contained in:
Jeffrey Wilcke 2017-03-13 21:45:05 +01:00
parent 87bbc432ab
commit 22ca13fa85
3 changed files with 50 additions and 35 deletions

View file

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

View file

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

View file

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