aboutsummaryrefslogtreecommitdiffstats
path: root/tests/util.go
diff options
context:
space:
mode:
authorJeffrey Wilcke <jeffrey@ethereum.org>2016-12-06 09:16:03 +0800
committerFelix Lange <fjl@twurst.com>2016-12-06 09:16:03 +0800
commit3fc7c978277051391f8ea7831559e9f4f83c3166 (patch)
treeb11b41c1723e02adc098ddc9f4188a8bad782ed8 /tests/util.go
parent7f79d249a64ee72b185ffa9a9ed78f137b7938de (diff)
downloaddexon-3fc7c978277051391f8ea7831559e9f4f83c3166.tar.gz
dexon-3fc7c978277051391f8ea7831559e9f4f83c3166.tar.zst
dexon-3fc7c978277051391f8ea7831559e9f4f83c3166.zip
core, core/vm: implemented a generic environment (#3348)
Environment is now a struct (not an interface). This reduces a lot of tech-debt throughout the codebase where a virtual machine environment had to be implemented in order to test or run it. The new environment is suitable to be used en the json tests, core consensus and light client.
Diffstat (limited to 'tests/util.go')
-rw-r--r--tests/util.go171
1 files changed, 49 insertions, 122 deletions
diff --git a/tests/util.go b/tests/util.go
index 53955a47f..b545a0cc8 100644
--- a/tests/util.go
+++ b/tests/util.go
@@ -18,6 +18,7 @@ package tests
import (
"bytes"
+ "encoding/hex"
"fmt"
"math/big"
"os"
@@ -148,137 +149,63 @@ type VmTest struct {
PostStateRoot string
}
-type Env struct {
- chainConfig *params.ChainConfig
- depth int
- state *state.StateDB
- skipTransfer bool
- initial bool
- Gas *big.Int
+func NewEVMEnvironment(vmTest bool, chainConfig *params.ChainConfig, statedb *state.StateDB, envValues map[string]string, tx map[string]string) (*vm.Environment, core.Message) {
+ var (
+ data = common.FromHex(tx["data"])
+ gas = common.Big(tx["gasLimit"])
+ price = common.Big(tx["gasPrice"])
+ value = common.Big(tx["value"])
+ nonce = common.Big(tx["nonce"]).Uint64()
+ )
- origin common.Address
- parent common.Hash
- coinbase common.Address
-
- number *big.Int
- time *big.Int
- difficulty *big.Int
- gasLimit *big.Int
-
- vmTest bool
-
- evm *vm.EVM
-}
-
-func NewEnv(chainConfig *params.ChainConfig, state *state.StateDB) *Env {
- env := &Env{
- chainConfig: chainConfig,
- state: state,
+ origin := common.HexToAddress(tx["caller"])
+ if len(tx["secretKey"]) > 0 {
+ key, _ := hex.DecodeString(tx["secretKey"])
+ origin = crypto.PubkeyToAddress(crypto.ToECDSA(key).PublicKey)
}
- return env
-}
-
-func NewEnvFromMap(chainConfig *params.ChainConfig, state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env {
- env := NewEnv(chainConfig, state)
-
- env.origin = common.HexToAddress(exeValues["caller"])
- env.parent = common.HexToHash(envValues["previousHash"])
- env.coinbase = common.HexToAddress(envValues["currentCoinbase"])
- env.number = common.Big(envValues["currentNumber"])
- env.time = common.Big(envValues["currentTimestamp"])
- env.difficulty = common.Big(envValues["currentDifficulty"])
- env.gasLimit = common.Big(envValues["currentGasLimit"])
- env.Gas = new(big.Int)
-
- env.evm = vm.New(env, vm.Config{
- EnableJit: EnableJit,
- ForceJit: ForceJit,
- })
- return env
-}
-
-func (self *Env) ChainConfig() *params.ChainConfig { return self.chainConfig }
-func (self *Env) Vm() vm.Vm { return self.evm }
-func (self *Env) Origin() common.Address { return self.origin }
-func (self *Env) BlockNumber() *big.Int { return self.number }
-func (self *Env) Coinbase() common.Address { return self.coinbase }
-func (self *Env) Time() *big.Int { return self.time }
-func (self *Env) Difficulty() *big.Int { return self.difficulty }
-func (self *Env) Db() vm.Database { return self.state }
-func (self *Env) GasLimit() *big.Int { return self.gasLimit }
-func (self *Env) VmType() vm.Type { return vm.StdVmTy }
-func (self *Env) GetHash(n uint64) common.Hash {
- return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String())))
-}
-func (self *Env) AddLog(log *vm.Log) {
- self.state.AddLog(log)
-}
-func (self *Env) Depth() int { return self.depth }
-func (self *Env) SetDepth(i int) { self.depth = i }
-func (self *Env) CanTransfer(from common.Address, balance *big.Int) bool {
- if self.skipTransfer {
- if self.initial {
- self.initial = false
- return true
- }
+ var to *common.Address
+ if len(tx["to"]) > 2 {
+ t := common.HexToAddress(tx["to"])
+ to = &t
}
- return self.state.GetBalance(from).Cmp(balance) >= 0
-}
-func (self *Env) SnapshotDatabase() int {
- return self.state.Snapshot()
-}
-func (self *Env) RevertToSnapshot(snapshot int) {
- self.state.RevertToSnapshot(snapshot)
-}
+ msg := types.NewMessage(origin, to, nonce, value, gas, price, data, true)
-func (self *Env) Transfer(from, to vm.Account, amount *big.Int) {
- if self.skipTransfer {
- return
- }
- core.Transfer(from, to, amount)
-}
-
-func (self *Env) Call(caller vm.ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
- if self.vmTest && self.depth > 0 {
- caller.ReturnGas(gas, price)
-
- return nil, nil
+ initialCall := true
+ canTransfer := func(db vm.StateDB, address common.Address, amount *big.Int) bool {
+ if vmTest {
+ if initialCall {
+ initialCall = false
+ return true
+ }
+ }
+ return core.CanTransfer(db, address, amount)
}
- ret, err := core.Call(self, caller, addr, data, gas, price, value)
- self.Gas = gas
-
- return ret, err
-
-}
-func (self *Env) CallCode(caller vm.ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
- if self.vmTest && self.depth > 0 {
- caller.ReturnGas(gas, price)
-
- return nil, nil
+ transfer := func(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {
+ if vmTest {
+ return
+ }
+ core.Transfer(db, sender, recipient, amount)
}
- return core.CallCode(self, caller, addr, data, gas, price, value)
-}
-func (self *Env) DelegateCall(caller vm.ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error) {
- if self.vmTest && self.depth > 0 {
- caller.ReturnGas(gas, price)
-
- return nil, nil
+ context := vm.Context{
+ CanTransfer: canTransfer,
+ Transfer: transfer,
+ GetHash: func(n uint64) common.Hash {
+ return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String())))
+ },
+
+ Origin: origin,
+ Coinbase: common.HexToAddress(envValues["currentCoinbase"]),
+ BlockNumber: common.Big(envValues["currentNumber"]),
+ Time: common.Big(envValues["currentTimestamp"]),
+ GasLimit: common.Big(envValues["currentGasLimit"]),
+ Difficulty: common.Big(envValues["currentDifficulty"]),
+ GasPrice: price,
}
- return core.DelegateCall(self, caller, addr, data, gas, price)
-}
-
-func (self *Env) Create(caller vm.ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) {
- if self.vmTest {
- caller.ReturnGas(gas, price)
-
- nonce := self.state.GetNonce(caller.Address())
- obj := self.state.GetOrNewStateObject(crypto.CreateAddress(caller.Address(), nonce))
-
- return nil, obj.Address(), nil
- } else {
- return core.Create(self, caller, data, gas, price, value)
+ if context.GasPrice == nil {
+ context.GasPrice = new(big.Int)
}
+ return vm.NewEnvironment(context, statedb, chainConfig, vm.Config{NoRecursion: vmTest}), msg
}