aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorjm <jm.huang@cobinhood.com>2019-01-16 17:32:29 +0800
committerJhih-Ming Huang <jm.huang@cobinhood.com>2019-05-06 10:44:03 +0800
commitd3b485a5af768db59bd648175849f961e25bc630 (patch)
treeec43033c9aa438969cea45fb9de19e50a88a5cd8 /core
parent266068a53cdf9e06acacf982d63653c03133a634 (diff)
downloaddexon-d3b485a5af768db59bd648175849f961e25bc630.tar
dexon-d3b485a5af768db59bd648175849f961e25bc630.tar.gz
dexon-d3b485a5af768db59bd648175849f961e25bc630.tar.bz2
dexon-d3b485a5af768db59bd648175849f961e25bc630.tar.lz
dexon-d3b485a5af768db59bd648175849f961e25bc630.tar.xz
dexon-d3b485a5af768db59bd648175849f961e25bc630.tar.zst
dexon-d3b485a5af768db59bd648175849f961e25bc630.zip
core: vm: extract stateDB and contract out
Extract stateDB and contract out from core/vm/evm to core/vm, such that other vm type can use the common modules.
Diffstat (limited to 'core')
-rw-r--r--core/evm.go2
-rw-r--r--core/state_transition.go15
-rw-r--r--core/vm/contract.go (renamed from core/vm/evm/contract.go)96
-rw-r--r--core/vm/contracts.go (renamed from core/vm/evm/contracts.go)37
-rw-r--r--core/vm/contracts_test.go (renamed from core/vm/evm/contracts_test.go)2
-rw-r--r--core/vm/evm/analysis.go28
-rw-r--r--core/vm/evm/evm.go114
-rw-r--r--core/vm/evm/evm_test.go21
-rw-r--r--core/vm/evm/gas_table.go56
-rw-r--r--core/vm/evm/governance.go22
-rw-r--r--core/vm/evm/governance_test.go9
-rw-r--r--core/vm/evm/instructions.go192
-rw-r--r--core/vm/evm/instructions_test.go16
-rw-r--r--core/vm/evm/interface.go53
-rw-r--r--core/vm/evm/interpreter.go6
-rw-r--r--core/vm/evm/jump_table.go4
-rw-r--r--core/vm/evm/logger.go8
-rw-r--r--core/vm/evm/logger_json.go4
-rw-r--r--core/vm/evm/logger_test.go4
-rw-r--r--core/vm/evm/memory_table.go5
-rw-r--r--core/vm/evm/runtime/env.go7
-rw-r--r--core/vm/evm/runtime/runtime.go5
-rw-r--r--core/vm/sqlvm/sqlvm.go50
-rw-r--r--core/vm/stateDB.go97
24 files changed, 459 insertions, 394 deletions
diff --git a/core/evm.go b/core/evm.go
index 83a789131..a2b61c535 100644
--- a/core/evm.go
+++ b/core/evm.go
@@ -23,7 +23,7 @@ import (
"github.com/dexon-foundation/dexon/consensus"
"github.com/dexon-foundation/dexon/core/state"
"github.com/dexon-foundation/dexon/core/types"
- vm "github.com/dexon-foundation/dexon/core/vm/evm"
+ "github.com/dexon-foundation/dexon/core/vm"
)
// ChainContext supports retrieving headers and consensus parameters from the
diff --git a/core/state_transition.go b/core/state_transition.go
index fddb187af..a9a700c2b 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -27,6 +27,7 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core/vm"
"github.com/dexon-foundation/dexon/core/vm/evm"
+ "github.com/dexon-foundation/dexon/core/vm/sqlvm"
"github.com/dexon-foundation/dexon/log"
"github.com/dexon-foundation/dexon/params"
)
@@ -70,8 +71,9 @@ type StateTransition struct {
initialGas uint64
value *big.Int
data []byte
- state evm.StateDB
+ state vm.StateDB
evm *evm.EVM
+ sqlvm *sqlvm.SQLVM
}
// Message represents a message sent to a contract.
@@ -246,7 +248,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
return
}
msg := st.msg
- sender := evm.AccountRef(msg.From())
+ sender := vm.AccountRef(msg.From())
homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber)
contractCreation := msg.To() == nil
@@ -260,14 +262,19 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
}
var (
- evm = st.evm
+ evm = st.evm
+ sqlvm = st.sqlvm
// vm errors do not effect consensus and are therefor
// not assigned to err, except for insufficient balance
// error.
vmerr error
)
if contractCreation {
- ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value)
+ if len(st.data) != 0 && st.data[0] == 0xed {
+ ret, _, st.gas, vmerr = sqlvm.Create(sender, st.data, st.gas, st.value)
+ } else {
+ ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value)
+ }
} else {
// Increment the nonce for the next transaction
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
diff --git a/core/vm/evm/contract.go b/core/vm/contract.go
index a7ce2ddfd..37ec41cae 100644
--- a/core/vm/evm/contract.go
+++ b/core/vm/contract.go
@@ -14,12 +14,13 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package evm
+package vm
import (
"math/big"
"github.com/dexon-foundation/dexon/common"
+ "github.com/dexon-foundation/dexon/crypto"
)
// ContractRef is a reference to the contract's backing object
@@ -34,7 +35,23 @@ type ContractRef interface {
// proves difficult because of the cached jump destinations which
// are fetched from the parent contract (i.e. the caller), which
// is a ContractRef.
-type AccountRef common.Address
+type (
+ AccountRef common.Address
+ Bitvec []byte
+)
+
+func (bits *Bitvec) Set(pos uint64) {
+ (*bits)[pos/8] |= 0x80 >> (pos % 8)
+}
+func (bits *Bitvec) Set8(pos uint64) {
+ (*bits)[pos/8] |= 0xFF >> (pos % 8)
+ (*bits)[pos/8+1] |= ^(0xFF >> (pos % 8))
+}
+
+// codeSegment checks if the position is in a code segment.
+func (bits *Bitvec) CodeSegment(pos uint64) bool {
+ return ((*bits)[pos/8] & (0x80 >> (pos % 8))) == 0
+}
// Address casts AccountRef to a Address
func (ar AccountRef) Address() common.Address { return (common.Address)(ar) }
@@ -49,8 +66,8 @@ type Contract struct {
caller ContractRef
self ContractRef
- jumpdests map[common.Hash]bitvec // Aggregated result of JUMPDEST analysis.
- analysis bitvec // Locally cached result of JUMPDEST analysis
+ Jumpdests map[common.Hash]Bitvec // Aggregated result of JUMPDEST analysis.
+ Analysis Bitvec // Locally cached result of JUMPDEST analysis
Code []byte
CodeHash common.Hash
@@ -58,7 +75,7 @@ type Contract struct {
Input []byte
Gas uint64
- value *big.Int
+ Value *big.Int
}
// NewContract returns a new contract environment for the execution of EVM.
@@ -67,53 +84,20 @@ func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uin
if parent, ok := caller.(*Contract); ok {
// Reuse JUMPDEST analysis from parent context if available.
- c.jumpdests = parent.jumpdests
+ c.Jumpdests = parent.Jumpdests
} else {
- c.jumpdests = make(map[common.Hash]bitvec)
+ c.Jumpdests = make(map[common.Hash]Bitvec)
}
// Gas should be a pointer so it can safely be reduced through the run
// This pointer will be off the state transition
c.Gas = gas
// ensures a value is set
- c.value = value
+ c.Value = value
return c
}
-func (c *Contract) validJumpdest(dest *big.Int) bool {
- udest := dest.Uint64()
- // PC cannot go beyond len(code) and certainly can't be bigger than 63bits.
- // Don't bother checking for JUMPDEST in that case.
- if dest.BitLen() >= 63 || udest >= uint64(len(c.Code)) {
- return false
- }
- // Only JUMPDESTs allowed for destinations
- if OpCode(c.Code[udest]) != JUMPDEST {
- return false
- }
- // Do we have a contract hash already?
- if c.CodeHash != (common.Hash{}) {
- // Does parent context have the analysis?
- analysis, exist := c.jumpdests[c.CodeHash]
- if !exist {
- // Do the analysis and save in parent context
- // We do not need to store it in c.analysis
- analysis = codeBitmap(c.Code)
- c.jumpdests[c.CodeHash] = analysis
- }
- return analysis.codeSegment(udest)
- }
- // We don't have the code hash, most likely a piece of initcode not already
- // in state trie. In that case, we do an analysis, and save it locally, so
- // we don't have to recalculate it for every JUMP instruction in the execution
- // However, we don't save it within the parent context
- if c.analysis == nil {
- c.analysis = codeBitmap(c.Code)
- }
- return c.analysis.codeSegment(udest)
-}
-
// AsDelegate sets the contract to be a delegate call and returns the current
// contract (for chaining calls)
func (c *Contract) AsDelegate() *Contract {
@@ -121,16 +105,11 @@ func (c *Contract) AsDelegate() *Contract {
// that caller is something other than a Contract.
parent := c.caller.(*Contract)
c.CallerAddress = parent.CallerAddress
- c.value = parent.value
+ c.Value = parent.Value
return c
}
-// GetOp returns the n'th element in the contract's byte array
-func (c *Contract) GetOp(n uint64) OpCode {
- return OpCode(c.GetByte(n))
-}
-
// GetByte returns the n'th byte in the contract's byte array
func (c *Contract) GetByte(n uint64) byte {
if n < uint64(len(c.Code)) {
@@ -162,11 +141,6 @@ func (c *Contract) Address() common.Address {
return c.self.Address()
}
-// Value returns the contracts value (sent to it from it's caller)
-func (c *Contract) Value() *big.Int {
- return c.value
-}
-
// SetCallCode sets the code of the contract and address of the backing data
// object
func (c *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) {
@@ -177,8 +151,20 @@ func (c *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []by
// SetCodeOptionalHash can be used to provide code, but it's optional to provide hash.
// In case hash is not provided, the jumpdest analysis will not be saved to the parent context
-func (c *Contract) SetCodeOptionalHash(addr *common.Address, codeAndHash *codeAndHash) {
- c.Code = codeAndHash.code
- c.CodeHash = codeAndHash.hash
+func (c *Contract) SetCodeOptionalHash(addr *common.Address, CodeAndHash *CodeAndHash) {
+ c.Code = CodeAndHash.Code
+ c.CodeHash = CodeAndHash.Hash()
c.CodeAddr = addr
}
+
+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
+}
diff --git a/core/vm/evm/contracts.go b/core/vm/contracts.go
index 52bb0a83b..0711c3030 100644
--- a/core/vm/evm/contracts.go
+++ b/core/vm/contracts.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package evm
+package vm
import (
"crypto/sha256"
@@ -23,7 +23,6 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/common/math"
- "github.com/dexon-foundation/dexon/core/vm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/crypto/bn256"
"github.com/dexon-foundation/dexon/params"
@@ -66,7 +65,7 @@ func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contr
if contract.UseGas(gas) {
return p.Run(input)
}
- return nil, vm.ErrOutOfGas
+ return nil, ErrOutOfGas
}
// ECRECOVER implemented as a native contract.
@@ -88,7 +87,7 @@ func (c *ecrecover) Run(input []byte) ([]byte, error) {
v := input[63] - 27
// tighter sig s values input homestead only apply to tx sigs
- if !vm.AllZero(input[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
+ if !AllZero(input[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
return nil, nil
}
// v needs to be at the end for libsecp256k1
@@ -167,9 +166,9 @@ var (
// RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *bigModExp) RequiredGas(input []byte) uint64 {
var (
- baseLen = new(big.Int).SetBytes(vm.GetData(input, 0, 32))
- expLen = new(big.Int).SetBytes(vm.GetData(input, 32, 32))
- modLen = new(big.Int).SetBytes(vm.GetData(input, 64, 32))
+ baseLen = new(big.Int).SetBytes(GetData(input, 0, 32))
+ expLen = new(big.Int).SetBytes(GetData(input, 32, 32))
+ modLen = new(big.Int).SetBytes(GetData(input, 64, 32))
)
if len(input) > 96 {
input = input[96:]
@@ -182,9 +181,9 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
expHead = new(big.Int)
} else {
if expLen.Cmp(big32) > 0 {
- expHead = new(big.Int).SetBytes(vm.GetData(input, baseLen.Uint64(), 32))
+ expHead = new(big.Int).SetBytes(GetData(input, baseLen.Uint64(), 32))
} else {
- expHead = new(big.Int).SetBytes(vm.GetData(input, baseLen.Uint64(), expLen.Uint64()))
+ expHead = new(big.Int).SetBytes(GetData(input, baseLen.Uint64(), expLen.Uint64()))
}
}
// Calculate the adjusted exponent length
@@ -226,9 +225,9 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
func (c *bigModExp) Run(input []byte) ([]byte, error) {
var (
- baseLen = new(big.Int).SetBytes(vm.GetData(input, 0, 32)).Uint64()
- expLen = new(big.Int).SetBytes(vm.GetData(input, 32, 32)).Uint64()
- modLen = new(big.Int).SetBytes(vm.GetData(input, 64, 32)).Uint64()
+ baseLen = new(big.Int).SetBytes(GetData(input, 0, 32)).Uint64()
+ expLen = new(big.Int).SetBytes(GetData(input, 32, 32)).Uint64()
+ modLen = new(big.Int).SetBytes(GetData(input, 64, 32)).Uint64()
)
if len(input) > 96 {
input = input[96:]
@@ -241,9 +240,9 @@ func (c *bigModExp) Run(input []byte) ([]byte, error) {
}
// Retrieve the operands and execute the exponentiation
var (
- base = new(big.Int).SetBytes(vm.GetData(input, 0, baseLen))
- exp = new(big.Int).SetBytes(vm.GetData(input, baseLen, expLen))
- mod = new(big.Int).SetBytes(vm.GetData(input, baseLen+expLen, modLen))
+ base = new(big.Int).SetBytes(GetData(input, 0, baseLen))
+ exp = new(big.Int).SetBytes(GetData(input, baseLen, expLen))
+ mod = new(big.Int).SetBytes(GetData(input, baseLen+expLen, modLen))
)
if mod.BitLen() == 0 {
// Modulo 0 is undefined, return zero
@@ -281,11 +280,11 @@ func (c *bn256Add) RequiredGas(input []byte) uint64 {
}
func (c *bn256Add) Run(input []byte) ([]byte, error) {
- x, err := newCurvePoint(vm.GetData(input, 0, 64))
+ x, err := newCurvePoint(GetData(input, 0, 64))
if err != nil {
return nil, err
}
- y, err := newCurvePoint(vm.GetData(input, 64, 64))
+ y, err := newCurvePoint(GetData(input, 64, 64))
if err != nil {
return nil, err
}
@@ -303,12 +302,12 @@ func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 {
}
func (c *bn256ScalarMul) Run(input []byte) ([]byte, error) {
- p, err := newCurvePoint(vm.GetData(input, 0, 64))
+ p, err := newCurvePoint(GetData(input, 0, 64))
if err != nil {
return nil, err
}
res := new(bn256.G1)
- res.ScalarMult(p, new(big.Int).SetBytes(vm.GetData(input, 64, 32)))
+ res.ScalarMult(p, new(big.Int).SetBytes(GetData(input, 64, 32)))
return res.Marshal(), nil
}
diff --git a/core/vm/evm/contracts_test.go b/core/vm/contracts_test.go
index 4b43f777b..f0090fcce 100644
--- a/core/vm/evm/contracts_test.go
+++ b/core/vm/contracts_test.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-package evm
+package vm
import (
"fmt"
diff --git a/core/vm/evm/analysis.go b/core/vm/evm/analysis.go
index 5e430f965..575af575e 100644
--- a/core/vm/evm/analysis.go
+++ b/core/vm/evm/analysis.go
@@ -16,30 +16,16 @@
package evm
-// bitvec is a bit vector which maps bytes in a program.
-// An unset bit means the byte is an opcode, a set bit means
-// it's data (i.e. argument of PUSHxx).
-type bitvec []byte
-
-func (bits *bitvec) set(pos uint64) {
- (*bits)[pos/8] |= 0x80 >> (pos % 8)
-}
-func (bits *bitvec) set8(pos uint64) {
- (*bits)[pos/8] |= 0xFF >> (pos % 8)
- (*bits)[pos/8+1] |= ^(0xFF >> (pos % 8))
-}
-
-// codeSegment checks if the position is in a code segment.
-func (bits *bitvec) codeSegment(pos uint64) bool {
- return ((*bits)[pos/8] & (0x80 >> (pos % 8))) == 0
-}
+import (
+ "github.com/dexon-foundation/dexon/core/vm"
+)
// codeBitmap collects data locations in code.
-func codeBitmap(code []byte) bitvec {
+func codeBitmap(code []byte) vm.Bitvec {
// The bitmap is 4 bytes longer than necessary, in case the code
// ends with a PUSH32, the algorithm will push zeroes onto the
// bitvector outside the bounds of the actual code.
- bits := make(bitvec, len(code)/8+1+4)
+ bits := make(vm.Bitvec, len(code)/8+1+4)
for pc := uint64(0); pc < uint64(len(code)); {
op := OpCode(code[pc])
@@ -47,11 +33,11 @@ func codeBitmap(code []byte) bitvec {
numbits := op - PUSH1 + 1
pc++
for ; numbits >= 8; numbits -= 8 {
- bits.set8(pc) // 8
+ bits.Set8(pc) // 8
pc += 8
}
for ; numbits > 0; numbits-- {
- bits.set(pc)
+ bits.Set(pc)
pc++
}
} else {
diff --git a/core/vm/evm/evm.go b/core/vm/evm/evm.go
index 11d25792e..28fe24574 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,37 +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
- Round *big.Int // Current round number.
-
- 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
@@ -118,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
@@ -146,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,
@@ -195,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
}
@@ -210,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 {
@@ -232,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
@@ -267,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
}
@@ -283,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)
@@ -306,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
}
@@ -317,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)
@@ -338,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
}
@@ -348,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.
@@ -376,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) {
@@ -417,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 {
@@ -425,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()
@@ -467,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)
}
diff --git a/core/vm/evm/evm_test.go b/core/vm/evm/evm_test.go
index 2e382c15f..ef5e8a6b0 100644
--- a/core/vm/evm/evm_test.go
+++ b/core/vm/evm/evm_test.go
@@ -29,6 +29,7 @@ import (
"github.com/dexon-foundation/dexon/accounts/abi"
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core/state"
+ vmlib "github.com/dexon-foundation/dexon/core/vm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
@@ -84,9 +85,9 @@ func newTestVM() *testVM {
panic(err)
}
- context := Context{
- CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true },
- Transfer: func(StateDB, common.Address, common.Address, *big.Int) {},
+ context := vmlib.Context{
+ CanTransfer: func(vmlib.StateDB, common.Address, *big.Int) bool { return true },
+ Transfer: func(vmlib.StateDB, common.Address, common.Address, *big.Int) {},
Time: big.NewInt(time.Now().UnixNano() / 1000000000),
BlockNumber: big.NewInt(0),
}
@@ -106,9 +107,9 @@ func (vm *testVM) create(caller string, code []byte, value *big.Int) (
ret []byte, contractAddr common.Address, err error) {
callerAddr := common.HexToAddress(caller)
contractAddr = crypto.CreateAddress(callerAddr, uint64(0))
- contract := NewContract(AccountRef(callerAddr),
- AccountRef(contractAddr), value, math.MaxUint64)
- contract.SetCodeOptionalHash(&callerAddr, &codeAndHash{code: code})
+ contract := vmlib.NewContract(vmlib.AccountRef(callerAddr),
+ vmlib.AccountRef(contractAddr), value, math.MaxUint64)
+ contract.SetCodeOptionalHash(&callerAddr, &vmlib.CodeAndHash{Code: code})
ret, err = vm.interpreter.Run(contract, nil, false)
if err != nil {
contractAddr = common.Address{}
@@ -126,17 +127,17 @@ func (vm *testVM) call(
}
func (vm *testVM) createContract(
- caller string, addr common.Address, value *big.Int) *Contract {
+ caller string, addr common.Address, value *big.Int) *vmlib.Contract {
callerAddr := common.HexToAddress(caller)
vm.evm.StateDB.CreateAccount(callerAddr)
- contract := NewContract(AccountRef(callerAddr),
- AccountRef(addr), value, math.MaxUint64)
+ contract := vmlib.NewContract(vmlib.AccountRef(callerAddr),
+ vmlib.AccountRef(addr), value, math.MaxUint64)
contract.SetCallCode(
&addr, vm.evm.StateDB.GetCodeHash(addr), vm.evm.StateDB.GetCode(addr))
return contract
}
-func (vm *testVM) callContract(contract *Contract, input []byte) (
+func (vm *testVM) callContract(contract *vmlib.Contract, input []byte) (
ret []byte, err error) {
if len(contract.Code) == 0 {
panic(fmt.Errorf("no code"))
diff --git a/core/vm/evm/gas_table.go b/core/vm/evm/gas_table.go
index 0087004cf..242494537 100644
--- a/core/vm/evm/gas_table.go
+++ b/core/vm/evm/gas_table.go
@@ -59,12 +59,12 @@ func memoryGasCost(mem *vm.Memory, newMemSize uint64) (uint64, error) {
}
func constGasFunc(gas uint64) gasFunc {
- return func(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+ return func(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return gas, nil
}
}
-func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
@@ -90,7 +90,7 @@ func gasCallDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *vm
return gas, nil
}
-func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
@@ -116,7 +116,7 @@ func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *
return gas, nil
}
-func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasSStore(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var (
y, x = stack.Back(1), stack.Back(0)
current = evm.StateDB.GetState(contract.Address(), common.BigToHash(x))
@@ -186,7 +186,7 @@ func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack
}
func makeGasLog(n uint64) gasFunc {
- return func(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+ return func(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
requestedSize, overflow := vm.BigUint64(stack.Back(1))
if overflow {
return 0, errGasUintOverflow
@@ -215,7 +215,7 @@ func makeGasLog(n uint64) gasFunc {
}
}
-func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasSha3(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var overflow bool
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
@@ -239,7 +239,7 @@ func gasSha3(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack,
return gas, nil
}
-func gasCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasCodeCopy(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
@@ -263,7 +263,7 @@ func gasCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Sta
return gas, nil
}
-func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
@@ -289,11 +289,11 @@ func gasExtCodeCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.
return gas, nil
}
-func gasExtCodeHash(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasExtCodeHash(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return gt.ExtcodeHash, nil
}
-func gasMLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasMLoad(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var overflow bool
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
@@ -305,7 +305,7 @@ func gasMLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack,
return gas, nil
}
-func gasMStore8(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasMStore8(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var overflow bool
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
@@ -317,7 +317,7 @@ func gasMStore8(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stac
return gas, nil
}
-func gasMStore(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasMStore(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var overflow bool
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
@@ -329,7 +329,7 @@ func gasMStore(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack
return gas, nil
}
-func gasCreate(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasCreate(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var overflow bool
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
@@ -341,7 +341,7 @@ func gasCreate(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack
return gas, nil
}
-func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasCreate2(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var overflow bool
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
@@ -364,19 +364,19 @@ func gasCreate2(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stac
return gas, nil
}
-func gasBalance(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasBalance(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return gt.Balance, nil
}
-func gasExtCodeSize(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasExtCodeSize(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return gt.ExtcodeSize, nil
}
-func gasSLoad(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasSLoad(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return gt.SLoad, nil
}
-func gasExp(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasExp(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
expByteLen := uint64((stack.Data[stack.Len()-2].BitLen() + 7) / 8)
var (
@@ -389,7 +389,7 @@ func gasExp(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, m
return gas, nil
}
-func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasCall(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var (
gas = gt.Calls
transfersValue = stack.Back(2).Sign() != 0
@@ -425,7 +425,7 @@ func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack,
return gas, nil
}
-func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasCallCode(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
gas := gt.Calls
if stack.Back(2).Sign() != 0 {
gas += params.CallValueTransferGas
@@ -449,15 +449,15 @@ func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Sta
return gas, nil
}
-func gasReturn(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasReturn(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return memoryGasCost(mem, memorySize)
}
-func gasRevert(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasRevert(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return memoryGasCost(mem, memorySize)
}
-func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasSuicide(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
var gas uint64
// EIP150 homestead gas reprice fork:
if evm.ChainConfig().IsEIP150(evm.BlockNumber) {
@@ -483,7 +483,7 @@ func gasSuicide(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stac
return gas, nil
}
-func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasDelegateCall(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
@@ -503,7 +503,7 @@ func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *vm
return gas, nil
}
-func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasStaticCall(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
gas, err := memoryGasCost(mem, memorySize)
if err != nil {
return 0, err
@@ -523,14 +523,14 @@ func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.S
return gas, nil
}
-func gasPush(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasPush(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return GasFastestStep, nil
}
-func gasSwap(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasSwap(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return GasFastestStep, nil
}
-func gasDup(gt params.GasTable, evm *EVM, contract *Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
+func gasDup(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stack, mem *vm.Memory, memorySize uint64) (uint64, error) {
return GasFastestStep, nil
}
diff --git a/core/vm/evm/governance.go b/core/vm/evm/governance.go
index 8b31d3a01..18e733342 100644
--- a/core/vm/evm/governance.go
+++ b/core/vm/evm/governance.go
@@ -86,7 +86,7 @@ func init() {
}
// RunGovernanceContract executes governance contract.
-func RunGovernanceContract(evm *EVM, input []byte, contract *Contract) (ret []byte, err error) {
+func RunGovernanceContract(evm *EVM, input []byte, contract *vm.Contract) (ret []byte, err error) {
if len(input) < 4 {
return nil, nil
}
@@ -574,7 +574,7 @@ func publicKeyToNodeID(pkBytes []byte) (Bytes32, error) {
// State manipulation helper fro the governance contract.
type GovernanceStateHelper struct {
- StateDB StateDB
+ StateDB vm.StateDB
}
func (s *GovernanceStateHelper) getState(loc common.Hash) common.Hash {
@@ -1529,10 +1529,10 @@ func (s *GovernanceStateHelper) emitFinePaid(nodeAddr common.Address, amount *bi
type GovernanceContract struct {
evm *EVM
state GovernanceStateHelper
- contract *Contract
+ contract *vm.Contract
}
-func newGovernanceContract(evm *EVM, contract *Contract) *GovernanceContract {
+func newGovernanceContract(evm *EVM, contract *vm.Contract) *GovernanceContract {
return &GovernanceContract{
evm: evm,
state: GovernanceStateHelper{evm.StateDB},
@@ -1777,7 +1777,7 @@ func (g *GovernanceContract) delegate(nodeAddr common.Address) ([]byte, error) {
}
caller := g.contract.Caller()
- value := g.contract.Value()
+ value := g.contract.Value
// Can not delegate if no fund was sent.
if value.Cmp(big.NewInt(0)) == 0 {
@@ -1792,11 +1792,11 @@ func (g *GovernanceContract) delegate(nodeAddr common.Address) ([]byte, error) {
// Add to the total staked of node.
node := g.state.Node(offset)
- node.Staked = new(big.Int).Add(node.Staked, g.contract.Value())
+ node.Staked = new(big.Int).Add(node.Staked, g.contract.Value)
g.state.UpdateNode(offset, node)
// Add to network total staked.
- g.state.IncTotalStaked(g.contract.Value())
+ g.state.IncTotalStaked(g.contract.Value)
// Push delegator record.
offset = g.state.LenDelegators(nodeAddr)
@@ -1855,7 +1855,7 @@ func (g *GovernanceContract) stake(
}
// Delegate fund to itself.
- if g.contract.Value().Cmp(big.NewInt(0)) > 0 {
+ if g.contract.Value.Cmp(big.NewInt(0)) > 0 {
if ret, err := g.delegate(caller); err != nil {
return ret, err
}
@@ -2013,16 +2013,16 @@ func (g *GovernanceContract) payFine(nodeAddr common.Address) ([]byte, error) {
}
node := g.state.Node(nodeOffset)
- if node.Fined.Cmp(big.NewInt(0)) <= 0 || node.Fined.Cmp(g.contract.Value()) < 0 {
+ if node.Fined.Cmp(big.NewInt(0)) <= 0 || node.Fined.Cmp(g.contract.Value) < 0 {
return nil, errExecutionReverted
}
- node.Fined = new(big.Int).Sub(node.Fined, g.contract.Value())
+ node.Fined = new(big.Int).Sub(node.Fined, g.contract.Value)
g.state.UpdateNode(nodeOffset, node)
// TODO: paid fine should be added to award pool.
- g.state.emitFinePaid(nodeAddr, g.contract.Value())
+ g.state.emitFinePaid(nodeAddr, g.contract.Value)
return g.useGas(100000)
}
diff --git a/core/vm/evm/governance_test.go b/core/vm/evm/governance_test.go
index 1a67516ec..5a82c7f1a 100644
--- a/core/vm/evm/governance_test.go
+++ b/core/vm/evm/governance_test.go
@@ -34,6 +34,7 @@ import (
"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/ethdb"
"github.com/dexon-foundation/dexon/params"
@@ -149,11 +150,11 @@ func (g *GovernanceContractTestSuite) newPrefundAccount() (*ecdsa.PrivateKey, co
}
func (g *GovernanceContractTestSuite) call(caller common.Address, input []byte, value *big.Int) ([]byte, error) {
- context := Context{
- CanTransfer: func(db StateDB, addr common.Address, amount *big.Int) bool {
+ context := vm.Context{
+ CanTransfer: func(db vm.StateDB, addr common.Address, amount *big.Int) bool {
return db.GetBalance(addr).Cmp(amount) >= 0
},
- Transfer: func(db StateDB, sender common.Address, recipient common.Address, amount *big.Int) {
+ Transfer: func(db vm.StateDB, sender common.Address, recipient common.Address, amount *big.Int) {
db.SubBalance(sender, amount)
db.AddBalance(recipient, amount)
},
@@ -173,7 +174,7 @@ func (g *GovernanceContractTestSuite) call(caller common.Address, input []byte,
}
evm := NewEVM(context, g.stateDB, params.TestChainConfig, Config{IsBlockProposer: true})
- ret, _, err := evm.Call(AccountRef(caller), GovernanceContractAddress, input, 10000000, value)
+ ret, _, err := evm.Call(vm.AccountRef(caller), GovernanceContractAddress, input, 10000000, value)
return ret, err
}
diff --git a/core/vm/evm/instructions.go b/core/vm/evm/instructions.go
index d37ab5e43..10ff75b69 100644
--- a/core/vm/evm/instructions.go
+++ b/core/vm/evm/instructions.go
@@ -51,7 +51,7 @@ func init() {
}
}
-func opAdd(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opAdd(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := stack.Pop(), stack.Peek()
math.U256(y.Add(x, y))
@@ -59,7 +59,7 @@ func opAdd(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
return nil, nil
}
-func opSub(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opSub(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := stack.Pop(), stack.Peek()
math.U256(y.Sub(x, y))
@@ -67,7 +67,7 @@ func opSub(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
return nil, nil
}
-func opMul(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opMul(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := stack.Pop(), stack.Pop()
stack.Push(math.U256(x.Mul(x, y)))
@@ -76,7 +76,7 @@ func opMul(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
return nil, nil
}
-func opDiv(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opDiv(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := stack.Pop(), stack.Peek()
if y.Sign() != 0 {
math.U256(y.Div(x, y))
@@ -87,7 +87,7 @@ func opDiv(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
return nil, nil
}
-func opSdiv(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opSdiv(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := math.S256(stack.Pop()), math.S256(stack.Pop())
res := interpreter.intPool.GetZero()
@@ -106,7 +106,7 @@ func opSdiv(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
return nil, nil
}
-func opMod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opMod(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := stack.Pop(), stack.Pop()
if y.Sign() == 0 {
stack.Push(x.SetUint64(0))
@@ -117,7 +117,7 @@ func opMod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
return nil, nil
}
-func opSmod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opSmod(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := math.S256(stack.Pop()), math.S256(stack.Pop())
res := interpreter.intPool.GetZero()
@@ -136,7 +136,7 @@ func opSmod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
return nil, nil
}
-func opExp(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opExp(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
base, exponent := stack.Pop(), stack.Pop()
if base.Cmp(big2) == 0 && exponent.Cmp(big256) == -1 {
exp := exponent.Int64()
@@ -150,7 +150,7 @@ func opExp(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
return nil, nil
}
-func opSignExtend(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opSignExtend(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
back := stack.Pop()
if back.Cmp(big.NewInt(31)) < 0 {
bit := uint(back.Uint64()*8 + 7)
@@ -170,13 +170,13 @@ func opSignExtend(pc *uint64, interpreter *EVMInterpreter, contract *Contract, m
return nil, nil
}
-func opNot(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opNot(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x := stack.Peek()
math.U256(x.Not(x))
return nil, nil
}
-func opLt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opLt(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := stack.Pop(), stack.Peek()
if x.Cmp(y) < 0 {
y.SetUint64(1)
@@ -187,7 +187,7 @@ func opLt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *v
return nil, nil
}
-func opGt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opGt(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := stack.Pop(), stack.Peek()
if x.Cmp(y) > 0 {
y.SetUint64(1)
@@ -198,7 +198,7 @@ func opGt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *v
return nil, nil
}
-func opSlt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opSlt(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := stack.Pop(), stack.Peek()
xSign := x.Cmp(tt255)
@@ -222,7 +222,7 @@ func opSlt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
return nil, nil
}
-func opSgt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opSgt(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := stack.Pop(), stack.Peek()
xSign := x.Cmp(tt255)
@@ -246,7 +246,7 @@ func opSgt(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
return nil, nil
}
-func opEq(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opEq(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := stack.Pop(), stack.Peek()
if x.Cmp(y) == 0 {
y.SetUint64(1)
@@ -257,7 +257,7 @@ func opEq(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *v
return nil, nil
}
-func opIszero(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opIszero(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x := stack.Peek()
if x.Sign() > 0 {
x.SetUint64(0)
@@ -267,7 +267,7 @@ func opIszero(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
return nil, nil
}
-func opAnd(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opAnd(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := stack.Pop(), stack.Pop()
stack.Push(x.And(x, y))
@@ -275,7 +275,7 @@ func opAnd(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
return nil, nil
}
-func opOr(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opOr(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := stack.Pop(), stack.Peek()
y.Or(x, y)
@@ -283,7 +283,7 @@ func opOr(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *v
return nil, nil
}
-func opXor(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opXor(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y := stack.Pop(), stack.Peek()
y.Xor(x, y)
@@ -291,7 +291,7 @@ func opXor(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
return nil, nil
}
-func opByte(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opByte(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
th, val := stack.Pop(), stack.Peek()
if th.Cmp(common.Big32) < 0 {
b := math.Byte(val, 32, int(th.Int64()))
@@ -303,7 +303,7 @@ func opByte(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
return nil, nil
}
-func opAddmod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opAddmod(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y, z := stack.Pop(), stack.Pop(), stack.Pop()
if z.Cmp(bigZero) > 0 {
x.Add(x, y)
@@ -316,7 +316,7 @@ func opAddmod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
return nil, nil
}
-func opMulmod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opMulmod(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
x, y, z := stack.Pop(), stack.Pop(), stack.Pop()
if z.Cmp(bigZero) > 0 {
x.Mul(x, y)
@@ -332,7 +332,7 @@ func opMulmod(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
// opSHL implements Shift Left
// The SHL instruction (shift left) pops 2 values from the stack, first arg1 and then arg2,
// and pushes on the stack arg2 shifted to the left by arg1 number of bits.
-func opSHL(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opSHL(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards
shift, value := math.U256(stack.Pop()), math.U256(stack.Peek())
defer interpreter.intPool.Put(shift) // First operand back into the pool
@@ -350,7 +350,7 @@ func opSHL(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
// opSHR implements Logical Shift Right
// The SHR instruction (logical shift right) pops 2 values from the stack, first arg1 and then arg2,
// and pushes on the stack arg2 shifted to the right by arg1 number of bits with zero fill.
-func opSHR(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opSHR(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards
shift, value := math.U256(stack.Pop()), math.U256(stack.Peek())
defer interpreter.intPool.Put(shift) // First operand back into the pool
@@ -368,7 +368,7 @@ func opSHR(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
// opSAR implements Arithmetic Shift Right
// The SAR instruction (arithmetic shift right) pops 2 values from the stack, first arg1 and then arg2,
// and pushes on the stack arg2 shifted to the right by arg1 number of bits with sign extension.
-func opSAR(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opSAR(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// Note, S256 returns (potentially) a new bigint, so we're popping, not peeking this one
shift, value := math.U256(stack.Pop()), math.S256(stack.Pop())
defer interpreter.intPool.Put(shift) // First operand back into the pool
@@ -389,7 +389,7 @@ func opSAR(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *
return nil, nil
}
-func opSha3(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opSha3(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
offset, size := stack.Pop(), stack.Pop()
data := memory.Get(offset.Int64(), size.Int64())
@@ -411,7 +411,7 @@ func opSha3(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
return nil, nil
}
-func opRand(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opRand(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
evm := interpreter.evm
nonce := evm.StateDB.GetNonce(evm.Origin)
@@ -433,43 +433,43 @@ func opRand(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
return nil, nil
}
-func opAddress(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opAddress(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(contract.Address().Big())
return nil, nil
}
-func opBalance(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opBalance(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
slot := stack.Peek()
slot.Set(interpreter.evm.StateDB.GetBalance(common.BigToAddress(slot)))
return nil, nil
}
-func opOrigin(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opOrigin(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(interpreter.evm.Origin.Big())
return nil, nil
}
-func opCaller(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opCaller(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(contract.Caller().Big())
return nil, nil
}
-func opCallValue(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
- stack.Push(interpreter.intPool.Get().Set(contract.value))
+func opCallValue(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ stack.Push(interpreter.intPool.Get().Set(contract.Value))
return nil, nil
}
-func opCallDataLoad(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opCallDataLoad(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(interpreter.intPool.Get().SetBytes(vm.GetDataBig(contract.Input, stack.Pop(), big32)))
return nil, nil
}
-func opCallDataSize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opCallDataSize(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(interpreter.intPool.Get().SetInt64(int64(len(contract.Input))))
return nil, nil
}
-func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
var (
memOffset = stack.Pop()
dataOffset = stack.Pop()
@@ -481,12 +481,12 @@ func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract,
return nil, nil
}
-func opReturnDataSize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opReturnDataSize(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(interpreter.intPool.Get().SetUint64(uint64(len(interpreter.returnData))))
return nil, nil
}
-func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
var (
memOffset = stack.Pop()
dataOffset = stack.Pop()
@@ -504,21 +504,21 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contrac
return nil, nil
}
-func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
slot := stack.Peek()
slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(common.BigToAddress(slot))))
return nil, nil
}
-func opCodeSize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opCodeSize(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
l := interpreter.intPool.Get().SetInt64(int64(len(contract.Code)))
stack.Push(l)
return nil, nil
}
-func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
var (
memOffset = stack.Pop()
codeOffset = stack.Pop()
@@ -531,7 +531,7 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, mem
return nil, nil
}
-func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
var (
addr = common.BigToAddress(stack.Pop())
memOffset = stack.Pop()
@@ -571,7 +571,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *Contract,
//
// (6) Caller tries to get the code hash for an account which is marked as deleted,
// this account should be regarded as a non-existent account and zero should be returned.
-func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
slot := stack.Peek()
address := common.BigToAddress(slot)
if interpreter.evm.StateDB.Empty(address) {
@@ -582,12 +582,12 @@ func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, contract *Contract,
return nil, nil
}
-func opGasprice(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opGasprice(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(interpreter.intPool.Get().Set(interpreter.evm.GasPrice))
return nil, nil
}
-func opBlockhash(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opBlockhash(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
num := stack.Pop()
n := interpreter.intPool.Get().Sub(interpreter.evm.BlockNumber, common.Big257)
@@ -600,37 +600,37 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, contract *Contract, me
return nil, nil
}
-func opCoinbase(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opCoinbase(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(interpreter.evm.Coinbase.Big())
return nil, nil
}
-func opTimestamp(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opTimestamp(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(math.U256(interpreter.intPool.Get().Set(interpreter.evm.Time)))
return nil, nil
}
-func opNumber(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opNumber(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(math.U256(interpreter.intPool.Get().Set(interpreter.evm.BlockNumber)))
return nil, nil
}
-func opDifficulty(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opDifficulty(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(math.U256(interpreter.intPool.Get().Set(interpreter.evm.Difficulty)))
return nil, nil
}
-func opGasLimit(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opGasLimit(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(math.U256(interpreter.intPool.Get().SetUint64(interpreter.evm.GasLimit)))
return nil, nil
}
-func opPop(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opPop(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
interpreter.intPool.Put(stack.Pop())
return nil, nil
}
-func opMload(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opMload(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
offset := stack.Pop()
val := interpreter.intPool.Get().SetBytes(memory.Get(offset.Int64(), 32))
stack.Push(val)
@@ -639,7 +639,7 @@ func opMload(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
return nil, nil
}
-func opMstore(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opMstore(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// pop value of the stack
mStart, val := stack.Pop(), stack.Pop()
memory.Set32(mStart.Uint64(), val)
@@ -648,21 +648,21 @@ func opMstore(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
return nil, nil
}
-func opMstore8(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opMstore8(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
off, val := stack.Pop().Int64(), stack.Pop().Int64()
memory.Store[off] = byte(val & 0xff)
return nil, nil
}
-func opSload(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opSload(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
loc := stack.Peek()
val := interpreter.evm.StateDB.GetState(contract.Address(), common.BigToHash(loc))
loc.SetBytes(val.Bytes())
return nil, nil
}
-func opSstore(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opSstore(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
loc := common.BigToHash(stack.Pop())
val := stack.Pop()
interpreter.evm.StateDB.SetState(contract.Address(), loc, common.BigToHash(val))
@@ -671,10 +671,10 @@ func opSstore(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
return nil, nil
}
-func opJump(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opJump(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
pos := stack.Pop()
- if !contract.validJumpdest(pos) {
- nop := contract.GetOp(pos.Uint64())
+ if !validJumpdest(pos, contract) {
+ nop := OpCode(contract.GetByte(pos.Uint64()))
return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos)
}
*pc = pos.Uint64()
@@ -683,11 +683,11 @@ func opJump(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
return nil, nil
}
-func opJumpi(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opJumpi(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
pos, cond := stack.Pop(), stack.Pop()
if cond.Sign() != 0 {
- if !contract.validJumpdest(pos) {
- nop := contract.GetOp(pos.Uint64())
+ if !validJumpdest(pos, contract) {
+ nop := OpCode(contract.GetByte(pos.Uint64()))
return nil, fmt.Errorf("invalid jump destination (%v) %v", nop, pos)
}
*pc = pos.Uint64()
@@ -699,26 +699,26 @@ func opJumpi(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
return nil, nil
}
-func opJumpdest(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opJumpdest(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
return nil, nil
}
-func opPc(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opPc(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(interpreter.intPool.Get().SetUint64(*pc))
return nil, nil
}
-func opMsize(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opMsize(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(interpreter.intPool.Get().SetInt64(int64(memory.Len())))
return nil, nil
}
-func opGas(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opGas(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Push(interpreter.intPool.Get().SetUint64(contract.Gas))
return nil, nil
}
-func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
var (
value = stack.Pop()
offset, size = stack.Pop(), stack.Pop()
@@ -751,7 +751,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
return nil, nil
}
-func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
var (
endowment = stack.Pop()
offset, size = stack.Pop(), stack.Pop()
@@ -779,7 +779,7 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo
return nil, nil
}
-func opCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opCall(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// Pop gas. The actual gas in interpreter.evm.callGasTemp.
interpreter.intPool.Put(stack.Pop())
gas := interpreter.evm.callGasTemp
@@ -808,7 +808,7 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
return ret, nil
}
-func opCallCode(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opCallCode(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
interpreter.intPool.Put(stack.Pop())
gas := interpreter.evm.callGasTemp
@@ -837,7 +837,7 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, contract *Contract, mem
return ret, nil
}
-func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
interpreter.intPool.Put(stack.Pop())
gas := interpreter.evm.callGasTemp
@@ -862,7 +862,7 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract,
return ret, nil
}
-func opStaticCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opStaticCall(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
interpreter.intPool.Put(stack.Pop())
gas := interpreter.evm.callGasTemp
@@ -887,7 +887,7 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, m
return ret, nil
}
-func opReturn(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opReturn(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
offset, size := stack.Pop(), stack.Pop()
ret := memory.GetPtr(offset.Int64(), size.Int64())
@@ -895,7 +895,7 @@ func opReturn(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
return ret, nil
}
-func opRevert(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opRevert(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
offset, size := stack.Pop(), stack.Pop()
ret := memory.GetPtr(offset.Int64(), size.Int64())
@@ -903,11 +903,11 @@ func opRevert(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memor
return ret, nil
}
-func opStop(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opStop(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
return nil, nil
}
-func opSuicide(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+func opSuicide(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
balance := interpreter.evm.StateDB.GetBalance(contract.Address())
interpreter.evm.StateDB.AddBalance(common.BigToAddress(stack.Pop()), balance)
@@ -919,7 +919,7 @@ func opSuicide(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo
// make log instruction function
func makeLog(size int) executionFunc {
- return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ return func(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
topics := make([]common.Hash, size)
mStart, mSize := stack.Pop(), stack.Pop()
for i := 0; i < size; i++ {
@@ -943,7 +943,7 @@ func makeLog(size int) executionFunc {
// make push instruction function
func makePush(size uint64, pushByteSize int) executionFunc {
- return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ return func(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
codeLen := len(contract.Code)
startMin := codeLen
@@ -966,7 +966,7 @@ func makePush(size uint64, pushByteSize int) executionFunc {
// make dup instruction function
func makeDup(size int64) executionFunc {
- return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ return func(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Dup(interpreter.intPool, int(size))
return nil, nil
}
@@ -976,8 +976,40 @@ func makeDup(size int64) executionFunc {
func makeSwap(size int64) executionFunc {
// switch n + 1 otherwise n would be swapped with n
size++
- return func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
+ return func(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) {
stack.Swap(int(size))
return nil, nil
}
}
+func validJumpdest(dest *big.Int, c *vm.Contract) bool {
+ udest := dest.Uint64()
+ // PC cannot go beyond len(code) and certainly can't be bigger than 63bits.
+ // Don't bother checking for JUMPDEST in that case.
+ if dest.BitLen() >= 63 || udest >= uint64(len(c.Code)) {
+ return false
+ }
+ // Only JUMPDESTs allowed for destinations
+ if OpCode(c.Code[udest]) != JUMPDEST {
+ return false
+ }
+ // Do we have a contract hash already?
+ if c.CodeHash != (common.Hash{}) {
+ // Does parent context have the analysis?
+ analysis, exist := c.Jumpdests[c.CodeHash]
+ if !exist {
+ // Do the analysis and save in parent context
+ // We do not need to store it in c.analysis
+ analysis = codeBitmap(c.Code)
+ c.Jumpdests[c.CodeHash] = analysis
+ }
+ return analysis.CodeSegment(udest)
+ }
+ // We don't have the code hash, most likely a piece of initcode not already
+ // in state trie. In that case, we do an analysis, and save it locally, so
+ // we don't have to recalculate it for every JUMP instruction in the execution
+ // However, we don't save it within the parent context
+ if c.Analysis == nil {
+ c.Analysis = codeBitmap(c.Code)
+ }
+ return c.Analysis.CodeSegment(udest)
+}
diff --git a/core/vm/evm/instructions_test.go b/core/vm/evm/instructions_test.go
index 9e677dde3..bd3df271d 100644
--- a/core/vm/evm/instructions_test.go
+++ b/core/vm/evm/instructions_test.go
@@ -33,9 +33,9 @@ type twoOperandTest struct {
expected string
}
-func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error)) {
+func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error)) {
var (
- env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
+ env = NewEVM(vm.Context{}, nil, params.TestChainConfig, Config{})
stack = NewStack()
pc = uint64(0)
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
@@ -76,7 +76,7 @@ func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64
func TestByteOp(t *testing.T) {
var (
- env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
+ env = NewEVM(vm.Context{}, nil, params.TestChainConfig, Config{})
stack = NewStack()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
)
@@ -209,9 +209,9 @@ func TestSLT(t *testing.T) {
testTwoOperandOp(t, tests, opSlt)
}
-func opBenchmark(bench *testing.B, op func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error), args ...string) {
+func opBenchmark(bench *testing.B, op func(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error), args ...string) {
var (
- env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
+ env = NewEVM(vm.Context{}, nil, params.TestChainConfig, Config{})
stack = NewStack()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
)
@@ -446,7 +446,7 @@ func BenchmarkOpIsZero(b *testing.B) {
func TestOpMstore(t *testing.T) {
var (
- env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
+ env = NewEVM(vm.Context{}, nil, params.TestChainConfig, Config{})
stack = NewStack()
mem = vm.NewMemory()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
@@ -472,7 +472,7 @@ func TestOpMstore(t *testing.T) {
func BenchmarkOpMstore(bench *testing.B) {
var (
- env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
+ env = NewEVM(vm.Context{}, nil, params.TestChainConfig, Config{})
stack = NewStack()
mem = vm.NewMemory()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
@@ -495,7 +495,7 @@ func BenchmarkOpMstore(bench *testing.B) {
func BenchmarkOpSHA3(bench *testing.B) {
var (
- env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
+ env = NewEVM(vm.Context{}, nil, params.TestChainConfig, Config{})
stack = NewStack()
mem = vm.NewMemory()
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
diff --git a/core/vm/evm/interface.go b/core/vm/evm/interface.go
index 20e5f34a9..2e751597a 100644
--- a/core/vm/evm/interface.go
+++ b/core/vm/evm/interface.go
@@ -20,61 +20,18 @@ import (
"math/big"
"github.com/dexon-foundation/dexon/common"
- "github.com/dexon-foundation/dexon/core/types"
+ "github.com/dexon-foundation/dexon/core/vm"
)
-// StateDB is an EVM database for full state querying.
-type StateDB interface {
- CreateAccount(common.Address)
-
- SubBalance(common.Address, *big.Int)
- AddBalance(common.Address, *big.Int)
- GetBalance(common.Address) *big.Int
-
- GetNonce(common.Address) uint64
- SetNonce(common.Address, uint64)
-
- GetCodeHash(common.Address) common.Hash
- GetCode(common.Address) []byte
- SetCode(common.Address, []byte)
- GetCodeSize(common.Address) int
-
- AddRefund(uint64)
- SubRefund(uint64)
- GetRefund() uint64
-
- GetCommittedState(common.Address, common.Hash) common.Hash
- GetState(common.Address, common.Hash) common.Hash
- SetState(common.Address, common.Hash, common.Hash)
-
- Suicide(common.Address) bool
- HasSuicided(common.Address) bool
-
- // Exist reports whether the given account exists in state.
- // Notably this should also return true for suicided accounts.
- Exist(common.Address) bool
- // Empty returns whether the given account is empty. Empty
- // is defined according to EIP161 (balance = nonce = code = 0).
- Empty(common.Address) bool
-
- RevertToSnapshot(int)
- Snapshot() int
-
- AddLog(*types.Log)
- AddPreimage(common.Hash, []byte)
-
- ForEachStorage(common.Address, func(common.Hash, common.Hash) bool)
-}
-
// CallContext provides a basic interface for the EVM calling conventions. The EVM
// depends on this context being implemented for doing subcalls and initialising new EVM contracts.
type CallContext interface {
// Call another contract
- Call(env *EVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
+ Call(env *EVM, me vm.ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
// Take another's contract code and execute within our own context
- CallCode(env *EVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
+ CallCode(env *EVM, me vm.ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
// Same as CallCode except sender and value is propagated from parent to child scope
- DelegateCall(env *EVM, me ContractRef, addr common.Address, data []byte, gas *big.Int) ([]byte, error)
+ DelegateCall(env *EVM, me vm.ContractRef, addr common.Address, data []byte, gas *big.Int) ([]byte, error)
// Create a new contract
- Create(env *EVM, me ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error)
+ Create(env *EVM, me vm.ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error)
}
diff --git a/core/vm/evm/interpreter.go b/core/vm/evm/interpreter.go
index ca3ddd05a..867e72ee1 100644
--- a/core/vm/evm/interpreter.go
+++ b/core/vm/evm/interpreter.go
@@ -59,7 +59,7 @@ type Config struct {
type Interpreter interface {
// Run loops and evaluates the contract's code with the given input data and returns
// the return byte-slice and an error if one occurred.
- Run(contract *Contract, input []byte, static bool) ([]byte, error)
+ Run(contract *vm.Contract, input []byte, static bool) ([]byte, error)
// CanRun tells if the contract, passed as an argument, can be
// run by the current interpreter. This is meant so that the
// caller can do something like:
@@ -144,7 +144,7 @@ func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, st
// It's important to note that any errors returned by the interpreter should be
// considered a revert-and-consume-all-gas operation except for
// errExecutionReverted which means revert-and-keep-gas-left.
-func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) {
+func (in *EVMInterpreter) Run(contract *vm.Contract, input []byte, readOnly bool) (ret []byte, err error) {
if in.intPool == nil {
in.intPool = vm.PoolOfIntPools.Get()
defer func() {
@@ -218,7 +218,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
// Get the operation from the jump table and validate the stack to ensure there are
// enough stack items available to perform the operation.
- op = contract.GetOp(pc)
+ op = OpCode(contract.GetByte(pc))
operation := in.cfg.JumpTable[op]
if !operation.valid {
return nil, fmt.Errorf("invalid opcode 0x%x", int(op))
diff --git a/core/vm/evm/jump_table.go b/core/vm/evm/jump_table.go
index da2f50c5a..da7cbfd04 100644
--- a/core/vm/evm/jump_table.go
+++ b/core/vm/evm/jump_table.go
@@ -25,8 +25,8 @@ import (
)
type (
- executionFunc func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error)
- gasFunc func(params.GasTable, *EVM, *Contract, *vm.Stack, *vm.Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64
+ executionFunc func(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error)
+ gasFunc func(params.GasTable, *EVM, *vm.Contract, *vm.Stack, *vm.Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64
memorySizeFunc func(*vm.Stack) *big.Int
)
diff --git a/core/vm/evm/logger.go b/core/vm/evm/logger.go
index f51943b14..d9ccfed03 100644
--- a/core/vm/evm/logger.go
+++ b/core/vm/evm/logger.go
@@ -100,8 +100,8 @@ func (s *StructLog) ErrorString() string {
// if you need to retain them beyond the current call.
type Tracer interface {
CaptureStart(from common.Address, to common.Address, call bool, input []byte, gas uint64, value *big.Int) error
- CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *Contract, depth int, err error) error
- CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *Contract, depth int, err error) error
+ CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error
+ CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error
CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) error
}
@@ -138,7 +138,7 @@ func (l *StructLogger) CaptureStart(from common.Address, to common.Address, crea
// CaptureState logs a new structured log message and pushes it out to the environment
//
// CaptureState also tracks SSTORE ops to track dirty values.
-func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *Contract, depth int, err error) error {
+func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error {
// check if already accumulated the specified number of logs
if l.cfg.Limit != 0 && l.cfg.Limit <= len(l.logs) {
return vm.ErrTraceLimitReached
@@ -187,7 +187,7 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
// CaptureFault implements the Tracer interface to trace an execution fault
// while running an opcode.
-func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *Contract, depth int, err error) error {
+func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error {
return nil
}
diff --git a/core/vm/evm/logger_json.go b/core/vm/evm/logger_json.go
index e96e435b3..b8c628684 100644
--- a/core/vm/evm/logger_json.go
+++ b/core/vm/evm/logger_json.go
@@ -47,7 +47,7 @@ func (l *JSONLogger) CaptureStart(from common.Address, to common.Address, create
}
// CaptureState outputs state information on the logger.
-func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *Contract, depth int, err error) error {
+func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error {
log := StructLog{
Pc: pc,
Op: op,
@@ -69,7 +69,7 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint
}
// CaptureFault outputs state information on the logger.
-func (l *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *Contract, depth int, err error) error {
+func (l *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *vm.Memory, stack *vm.Stack, contract *vm.Contract, depth int, err error) error {
return nil
}
diff --git a/core/vm/evm/logger_test.go b/core/vm/evm/logger_test.go
index a8e0e9044..3a293675b 100644
--- a/core/vm/evm/logger_test.go
+++ b/core/vm/evm/logger_test.go
@@ -51,11 +51,11 @@ func (*dummyStatedb) GetRefund() uint64 { return 1337 }
func TestStoreCapture(t *testing.T) {
var (
- env = NewEVM(Context{}, &dummyStatedb{}, params.TestChainConfig, Config{})
+ env = NewEVM(vm.Context{}, &dummyStatedb{}, params.TestChainConfig, Config{})
logger = NewStructLogger(nil)
mem = vm.NewMemory()
stack = NewStack()
- contract = NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 0)
+ contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 0)
)
stack.Push(big.NewInt(1))
stack.Push(big.NewInt(0))
diff --git a/core/vm/evm/memory_table.go b/core/vm/evm/memory_table.go
index c27e95a4a..f13cb6e81 100644
--- a/core/vm/evm/memory_table.go
+++ b/core/vm/evm/memory_table.go
@@ -23,6 +23,11 @@ import (
"github.com/dexon-foundation/dexon/core/vm"
)
+var (
+ big1 = big.NewInt(1)
+ big32 = big.NewInt(32)
+)
+
func memorySha3(stack *vm.Stack) *big.Int {
return vm.CalcMemSize(stack.Back(0), stack.Back(1))
}
diff --git a/core/vm/evm/runtime/env.go b/core/vm/evm/runtime/env.go
index c46580140..92cc8681c 100644
--- a/core/vm/evm/runtime/env.go
+++ b/core/vm/evm/runtime/env.go
@@ -19,10 +19,11 @@ package runtime
import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core"
- vm "github.com/dexon-foundation/dexon/core/vm/evm"
+ "github.com/dexon-foundation/dexon/core/vm"
+ "github.com/dexon-foundation/dexon/core/vm/evm"
)
-func NewEnv(cfg *Config) *vm.EVM {
+func NewEnv(cfg *Config) *evm.EVM {
context := vm.Context{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
@@ -37,5 +38,5 @@ func NewEnv(cfg *Config) *vm.EVM {
GasPrice: cfg.GasPrice,
}
- return vm.NewEVM(context, cfg.State, cfg.ChainConfig, cfg.EVMConfig)
+ return evm.NewEVM(context, cfg.State, cfg.ChainConfig, cfg.EVMConfig)
}
diff --git a/core/vm/evm/runtime/runtime.go b/core/vm/evm/runtime/runtime.go
index 93e6322f4..c89f9dd11 100644
--- a/core/vm/evm/runtime/runtime.go
+++ b/core/vm/evm/runtime/runtime.go
@@ -23,7 +23,8 @@ import (
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core/state"
- vm "github.com/dexon-foundation/dexon/core/vm/evm"
+ "github.com/dexon-foundation/dexon/core/vm"
+ "github.com/dexon-foundation/dexon/core/vm/evm"
"github.com/dexon-foundation/dexon/crypto"
"github.com/dexon-foundation/dexon/ethdb"
"github.com/dexon-foundation/dexon/params"
@@ -42,7 +43,7 @@ type Config struct {
GasPrice *big.Int
Value *big.Int
Debug bool
- EVMConfig vm.Config
+ EVMConfig evm.Config
State *state.StateDB
GetHashFn func(n uint64) common.Hash
diff --git a/core/vm/sqlvm/sqlvm.go b/core/vm/sqlvm/sqlvm.go
new file mode 100644
index 000000000..258a65d01
--- /dev/null
+++ b/core/vm/sqlvm/sqlvm.go
@@ -0,0 +1,50 @@
+package sqlvm
+
+import (
+ "math/big"
+
+ "github.com/dexon-foundation/dexon/common"
+ "github.com/dexon-foundation/dexon/core/vm"
+ "github.com/dexon-foundation/dexon/crypto"
+ "github.com/dexon-foundation/dexon/params"
+)
+
+type SQLVM struct {
+ // Context provides auxiliary blockchain related information
+ vm.Context
+ // StateDB gives access to the underlying state
+ StateDB vm.StateDB
+ // Depth is the current call stack
+ depth int
+
+ // chainConfig contains information about the current chain
+ chainConfig *params.ChainConfig
+ // chain rules contains the chain rules for the current epoch
+ chainRules params.Rules
+ // abort is used to abort the SQLVM calling operations
+ // NOTE: must be set atomically
+ abort int32
+ // callGasTemp holds the gas available for the current call. This is needed because the
+ // available gas is calculated in gasCall* according to the 63/64 rule and later
+ // applied in opCall*.
+ callGasTemp uint64
+}
+
+func (sqlvm *SQLVM) 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(), sqlvm.StateDB.GetNonce(caller.Address()))
+ return sqlvm.create(caller, &vm.CodeAndHash{Code: code}, gas, value, contractAddr)
+}
+
+// create creates a new contract using code as deployment code.
+func (sqlvm *SQLVM) 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
+ if sqlvm.depth > int(params.CallCreateDepth) {
+ return nil, common.Address{}, gas, vm.ErrDepth
+ }
+ // TODO (JM) implement create database contract function
+ return nil, common.Address{}, gas, nil
+}
diff --git a/core/vm/stateDB.go b/core/vm/stateDB.go
new file mode 100644
index 000000000..753b04247
--- /dev/null
+++ b/core/vm/stateDB.go
@@ -0,0 +1,97 @@
+package vm
+
+import (
+ "math/big"
+
+ "github.com/dexon-foundation/dexon/common"
+ "github.com/dexon-foundation/dexon/core/state"
+ "github.com/dexon-foundation/dexon/core/types"
+)
+
+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)
+)
+
+// 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
+ Round *big.Int // Current round number.
+
+ RandCallIndex uint64 // Number of times opRand is called
+}
+
+// StateDB is an EVM database for full state querying.
+type StateDB interface {
+ CreateAccount(common.Address)
+
+ SubBalance(common.Address, *big.Int)
+ AddBalance(common.Address, *big.Int)
+ GetBalance(common.Address) *big.Int
+
+ GetNonce(common.Address) uint64
+ SetNonce(common.Address, uint64)
+
+ GetCodeHash(common.Address) common.Hash
+ GetCode(common.Address) []byte
+ SetCode(common.Address, []byte)
+ GetCodeSize(common.Address) int
+
+ AddRefund(uint64)
+ SubRefund(uint64)
+ GetRefund() uint64
+
+ GetCommittedState(common.Address, common.Hash) common.Hash
+ GetState(common.Address, common.Hash) common.Hash
+ SetState(common.Address, common.Hash, common.Hash)
+
+ Suicide(common.Address) bool
+ HasSuicided(common.Address) bool
+
+ // Exist reports whether the given account exists in state.
+ // Notably this should also return true for suicided accounts.
+ Exist(common.Address) bool
+ // Empty returns whether the given account is empty. Empty
+ // is defined according to EIP161 (balance = nonce = code = 0).
+ Empty(common.Address) bool
+
+ RevertToSnapshot(int)
+ Snapshot() int
+
+ AddLog(*types.Log)
+ AddPreimage(common.Hash, []byte)
+
+ ForEachStorage(common.Address, func(common.Hash, common.Hash) bool)
+}