aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm/evm/evm.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/vm/evm/evm.go')
-rw-r--r--core/vm/evm/evm.go113
1 files changed, 28 insertions, 85 deletions
diff --git a/core/vm/evm/evm.go b/core/vm/evm/evm.go
index f34413727..45b821e94 100644
--- a/core/vm/evm/evm.go
+++ b/core/vm/evm/evm.go
@@ -22,7 +22,6 @@ import (
"time"
"github.com/dexon-foundation/dexon/common"
- "github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/vm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/params"
@@ -32,32 +31,18 @@ import (
// deployed contract addresses (relevant after the account abstraction).
var emptyCodeHash = crypto.Keccak256Hash(nil)
-type (
- // CanTransferFunc is the signature of a transfer guard function
- CanTransferFunc func(StateDB, common.Address, *big.Int) bool
- // TransferFunc is the signature of a transfer function
- TransferFunc func(StateDB, common.Address, common.Address, *big.Int)
- // GetHashFunc returns the nth block hash in the blockchain
- // and is used by the BLOCKHASH EVM op code.
- GetHashFunc func(uint64) common.Hash
- // StateAtFunc returns the statedb given a root hash.
- StateAtNumberFunc func(uint64) (*state.StateDB, error)
- // GetRoundHeightFunc returns the round height.
- GetRoundHeightFunc func(uint64) (uint64, bool)
-)
-
// run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter.
-func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) {
+func run(evm *EVM, contract *vm.Contract, input []byte, readOnly bool) ([]byte, error) {
if contract.CodeAddr != nil {
if o := OracleContracts[*contract.CodeAddr]; o != nil {
return RunOracleContract(o, evm, input, contract)
}
- precompiles := PrecompiledContractsHomestead
+ precompiles := vm.PrecompiledContractsHomestead
if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
- precompiles = PrecompiledContractsByzantium
+ precompiles = vm.PrecompiledContractsByzantium
}
if p := precompiles[*contract.CodeAddr]; p != nil {
- return RunPrecompiledContract(p, input, contract)
+ return vm.RunPrecompiledContract(p, input, contract)
}
}
for _, interpreter := range evm.interpreters {
@@ -76,36 +61,6 @@ func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, err
return nil, vm.ErrNoCompatibleInterpreter
}
-// Context provides the EVM with auxiliary information. Once provided
-// it shouldn't be modified.
-type Context struct {
- // CanTransfer returns whether the account contains
- // sufficient ether to transfer the value
- CanTransfer CanTransferFunc
- // Transfer transfers ether from one account to the other
- Transfer TransferFunc
- // GetHash returns the hash corresponding to n
- GetHash GetHashFunc
- // StateAtNumber returns the statedb given a root hash.
- StateAtNumber StateAtNumberFunc
- // GetRoundHeight returns the round height.
- GetRoundHeight GetRoundHeightFunc
-
- // Message information
- Origin common.Address // Provides information for ORIGIN
- GasPrice *big.Int // Provides information for GASPRICE
-
- // Block information
- Coinbase common.Address // Provides information for COINBASE
- GasLimit uint64 // Provides information for GASLIMIT
- BlockNumber *big.Int // Provides information for NUMBER
- Time *big.Int // Provides information for TIME
- Randomness []byte // Provides information for RAND
- Difficulty *big.Int // Provides information for DIFFICULTY
-
- RandCallIndex uint64 // Number of times opRand is called
-}
-
// EVM is the Ethereum Virtual Machine base object and provides
// the necessary tools to run a contract on the given state with
// the provided context. It should be noted that any error
@@ -117,9 +72,9 @@ type Context struct {
// The EVM should never be reused and is not thread safe.
type EVM struct {
// Context provides auxiliary blockchain related information
- Context
+ vm.Context
// StateDB gives access to the underlying state
- StateDB StateDB
+ StateDB vm.StateDB
// Depth is the current call stack
depth int
@@ -145,7 +100,7 @@ type EVM struct {
// NewEVM returns a new EVM. The returned EVM is not thread safe and should
// only ever be used *once*.
-func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
+func NewEVM(ctx vm.Context, statedb vm.StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
evm := &EVM{
Context: ctx,
StateDB: statedb,
@@ -194,7 +149,7 @@ func (evm *EVM) Interpreter() Interpreter {
// parameters. It also handles any necessary value transfer required and takes
// the necessary steps to create accounts and reverses the state in case of an
// execution error or failed value transfer.
-func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
+func (evm *EVM) Call(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
if evm.vmConfig.NoRecursion && evm.depth > 0 {
return nil, gas, nil
}
@@ -209,13 +164,13 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
}
var (
- to = AccountRef(addr)
+ to = vm.AccountRef(addr)
snapshot = evm.StateDB.Snapshot()
)
if !evm.StateDB.Exist(addr) {
- precompiles := PrecompiledContractsHomestead
+ precompiles := vm.PrecompiledContractsHomestead
if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
- precompiles = PrecompiledContractsByzantium
+ precompiles = vm.PrecompiledContractsByzantium
}
if precompiles[addr] == nil && OracleContracts[addr] == nil &&
evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
@@ -231,7 +186,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
// Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only.
- contract := NewContract(caller, to, value, gas)
+ contract := vm.NewContract(caller, to, value, gas)
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
// Even if the account has no code, we need to continue because it might be a precompile
@@ -266,7 +221,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
//
// CallCode differs from Call in the sense that it executes the given address'
// code with the caller as context.
-func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
+func (evm *EVM) CallCode(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
if evm.vmConfig.NoRecursion && evm.depth > 0 {
return nil, gas, nil
}
@@ -282,12 +237,12 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
var (
snapshot = evm.StateDB.Snapshot()
- to = AccountRef(caller.Address())
+ to = vm.AccountRef(caller.Address())
)
// initialise a new contract and set the code that is to be used by the
// EVM. The contract is a scoped environment for this execution context
// only.
- contract := NewContract(caller, to, value, gas)
+ contract := vm.NewContract(caller, to, value, gas)
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
ret, err = run(evm, contract, input, false)
@@ -305,7 +260,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
//
// DelegateCall differs from CallCode in the sense that it executes the given address'
// code with the caller as context and the caller is set to the caller of the caller.
-func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
+func (evm *EVM) DelegateCall(caller vm.ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
if evm.vmConfig.NoRecursion && evm.depth > 0 {
return nil, gas, nil
}
@@ -316,11 +271,11 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
var (
snapshot = evm.StateDB.Snapshot()
- to = AccountRef(caller.Address())
+ to = vm.AccountRef(caller.Address())
)
// Initialise a new contract and make initialise the delegate values
- contract := NewContract(caller, to, nil, gas).AsDelegate()
+ contract := vm.NewContract(caller, to, nil, gas).AsDelegate()
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
ret, err = run(evm, contract, input, false)
@@ -337,7 +292,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
// as parameters while disallowing any modifications to the state during the call.
// Opcodes that attempt to perform such modifications will result in exceptions
// instead of performing the modifications.
-func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
+func (evm *EVM) StaticCall(caller vm.ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
if evm.vmConfig.NoRecursion && evm.depth > 0 {
return nil, gas, nil
}
@@ -347,13 +302,13 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
}
var (
- to = AccountRef(addr)
+ to = vm.AccountRef(addr)
snapshot = evm.StateDB.Snapshot()
)
// Initialise a new contract and set the code that is to be used by the
// EVM. The contract is a scoped environment for this execution context
// only.
- contract := NewContract(caller, to, new(big.Int), gas)
+ contract := vm.NewContract(caller, to, new(big.Int), gas)
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
// We do an AddBalance of zero here, just in order to trigger a touch.
@@ -375,20 +330,8 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
return ret, contract.Gas, err
}
-type codeAndHash struct {
- code []byte
- hash common.Hash
-}
-
-func (c *codeAndHash) Hash() common.Hash {
- if c.hash == (common.Hash{}) {
- c.hash = crypto.Keccak256Hash(c.code)
- }
- return c.hash
-}
-
// create creates a new contract using code as deployment code.
-func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) {
+func (evm *EVM) create(caller vm.ContractRef, codeAndHash *vm.CodeAndHash, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) {
// Depth check execution. Fail if we're trying to execute above the
// limit.
if evm.depth > int(params.CallCreateDepth) {
@@ -416,7 +359,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
// initialise a new contract and set the code that is to be used by the
// EVM. The contract is a scoped environment for this execution context
// only.
- contract := NewContract(caller, AccountRef(address), value, gas)
+ contract := vm.NewContract(caller, vm.AccountRef(address), value, gas)
contract.SetCodeOptionalHash(&address, codeAndHash)
if evm.vmConfig.NoRecursion && evm.depth > 0 {
@@ -424,7 +367,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
}
if evm.vmConfig.Debug && evm.depth == 0 {
- evm.vmConfig.Tracer.CaptureStart(caller.Address(), address, true, codeAndHash.code, gas, value)
+ evm.vmConfig.Tracer.CaptureStart(caller.Address(), address, true, codeAndHash.Code, gas, value)
}
start := time.Now()
@@ -466,17 +409,17 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
}
// Create creates a new contract using code as deployment code.
-func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
+func (evm *EVM) Create(caller vm.ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address()))
- return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr)
+ return evm.create(caller, &vm.CodeAndHash{Code: code}, gas, value, contractAddr)
}
// Create2 creates a new contract using code as deployment code.
//
// The different between Create2 with Create is Create2 uses sha3(0xff ++ msg.sender ++ salt ++ sha3(init_code))[12:]
// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
-func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
- codeAndHash := &codeAndHash{code: code}
+func (evm *EVM) Create2(caller vm.ContractRef, code []byte, gas uint64, endowment *big.Int, salt *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
+ codeAndHash := &vm.CodeAndHash{Code: code}
contractAddr = crypto.CreateAddress2(caller.Address(), common.BigToHash(salt), codeAndHash.Hash().Bytes())
return evm.create(caller, codeAndHash, gas, endowment, contractAddr)
}