github.com/karalabe/go-ethereum@v0.8.5/tests/helper/vm.go (about)

     1  package helper
     2  
     3  import (
     4  	"errors"
     5  	"math/big"
     6  
     7  	"github.com/ethereum/go-ethereum/core"
     8  	"github.com/ethereum/go-ethereum/crypto"
     9  	"github.com/ethereum/go-ethereum/ethutil"
    10  	"github.com/ethereum/go-ethereum/state"
    11  	"github.com/ethereum/go-ethereum/vm"
    12  )
    13  
    14  type Env struct {
    15  	depth        int
    16  	state        *state.StateDB
    17  	skipTransfer bool
    18  	initial      bool
    19  	Gas          *big.Int
    20  
    21  	origin   []byte
    22  	parent   []byte
    23  	coinbase []byte
    24  
    25  	number     *big.Int
    26  	time       int64
    27  	difficulty *big.Int
    28  	gasLimit   *big.Int
    29  
    30  	logs state.Logs
    31  }
    32  
    33  func NewEnv(state *state.StateDB) *Env {
    34  	return &Env{
    35  		state: state,
    36  	}
    37  }
    38  
    39  func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env {
    40  	env := NewEnv(state)
    41  
    42  	env.origin = ethutil.Hex2Bytes(exeValues["caller"])
    43  	env.parent = ethutil.Hex2Bytes(envValues["previousHash"])
    44  	env.coinbase = ethutil.Hex2Bytes(envValues["currentCoinbase"])
    45  	env.number = ethutil.Big(envValues["currentNumber"])
    46  	env.time = ethutil.Big(envValues["currentTimestamp"]).Int64()
    47  	env.difficulty = ethutil.Big(envValues["currentDifficulty"])
    48  	env.gasLimit = ethutil.Big(envValues["currentGasLimit"])
    49  	env.Gas = new(big.Int)
    50  
    51  	return env
    52  }
    53  
    54  func (self *Env) Origin() []byte        { return self.origin }
    55  func (self *Env) BlockNumber() *big.Int { return self.number }
    56  func (self *Env) PrevHash() []byte      { return self.parent }
    57  func (self *Env) Coinbase() []byte      { return self.coinbase }
    58  func (self *Env) Time() int64           { return self.time }
    59  func (self *Env) Difficulty() *big.Int  { return self.difficulty }
    60  func (self *Env) State() *state.StateDB { return self.state }
    61  func (self *Env) GasLimit() *big.Int    { return self.gasLimit }
    62  func (self *Env) VmType() vm.Type       { return vm.StdVmTy }
    63  func (self *Env) GetHash(n uint64) []byte {
    64  	return crypto.Sha3([]byte(big.NewInt(int64(n)).String()))
    65  }
    66  func (self *Env) AddLog(log state.Log) {
    67  	self.logs = append(self.logs, log)
    68  }
    69  func (self *Env) Depth() int     { return self.depth }
    70  func (self *Env) SetDepth(i int) { self.depth = i }
    71  func (self *Env) Transfer(from, to vm.Account, amount *big.Int) error {
    72  	if self.skipTransfer {
    73  		// ugly hack
    74  		if self.initial {
    75  			self.initial = false
    76  			return nil
    77  		}
    78  
    79  		if from.Balance().Cmp(amount) < 0 {
    80  			return errors.New("Insufficient balance in account")
    81  		}
    82  
    83  		return nil
    84  	}
    85  	return vm.Transfer(from, to, amount)
    86  }
    87  
    88  func (self *Env) vm(addr, data []byte, gas, price, value *big.Int) *core.Execution {
    89  	exec := core.NewExecution(self, addr, data, gas, price, value)
    90  
    91  	return exec
    92  }
    93  
    94  func (self *Env) Call(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) {
    95  	exe := self.vm(addr, data, gas, price, value)
    96  	ret, err := exe.Call(addr, caller)
    97  	self.Gas = exe.Gas
    98  
    99  	return ret, err
   100  }
   101  func (self *Env) CallCode(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) {
   102  	exe := self.vm(caller.Address(), data, gas, price, value)
   103  	return exe.Call(addr, caller)
   104  }
   105  
   106  func (self *Env) Create(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) {
   107  	exe := self.vm(addr, data, gas, price, value)
   108  	return exe.Create(caller)
   109  }
   110  
   111  func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Logs, *big.Int, error) {
   112  	var (
   113  		to    = FromHex(exec["address"])
   114  		from  = FromHex(exec["caller"])
   115  		data  = FromHex(exec["data"])
   116  		gas   = ethutil.Big(exec["gas"])
   117  		price = ethutil.Big(exec["gasPrice"])
   118  		value = ethutil.Big(exec["value"])
   119  	)
   120  	// Reset the pre-compiled contracts for VM tests.
   121  	vm.Precompiled = make(map[string]*vm.PrecompiledAccount)
   122  
   123  	caller := state.GetOrNewStateObject(from)
   124  
   125  	vmenv := NewEnvFromMap(state, env, exec)
   126  	vmenv.skipTransfer = true
   127  	vmenv.initial = true
   128  	ret, err := vmenv.Call(caller, to, data, gas, price, value)
   129  
   130  	return ret, vmenv.logs, vmenv.Gas, err
   131  }
   132  
   133  func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) {
   134  	var (
   135  		keyPair, _ = crypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(tx["secretKey"])))
   136  		to         = FromHex(tx["to"])
   137  		data       = FromHex(tx["data"])
   138  		gas        = ethutil.Big(tx["gasLimit"])
   139  		price      = ethutil.Big(tx["gasPrice"])
   140  		value      = ethutil.Big(tx["value"])
   141  		caddr      = FromHex(env["currentCoinbase"])
   142  	)
   143  
   144  	// Set pre compiled contracts
   145  	vm.Precompiled = vm.PrecompiledContracts()
   146  
   147  	coinbase := statedb.GetOrNewStateObject(caddr)
   148  	coinbase.SetGasPool(ethutil.Big(env["currentGasLimit"]))
   149  
   150  	message := NewMessage(keyPair.Address(), to, data, value, gas, price)
   151  	vmenv := NewEnvFromMap(statedb, env, tx)
   152  	st := core.NewStateTransition(vmenv, message, coinbase)
   153  	vmenv.origin = keyPair.Address()
   154  	ret, err := st.TransitionState()
   155  	statedb.Update(vmenv.Gas)
   156  
   157  	return ret, vmenv.logs, vmenv.Gas, err
   158  }
   159  
   160  type Message struct {
   161  	from, to          []byte
   162  	value, gas, price *big.Int
   163  	data              []byte
   164  }
   165  
   166  func NewMessage(from, to, data []byte, value, gas, price *big.Int) Message {
   167  	return Message{from, to, value, gas, price, data}
   168  }
   169  
   170  func (self Message) Hash() []byte       { return nil }
   171  func (self Message) From() []byte       { return self.from }
   172  func (self Message) To() []byte         { return self.to }
   173  func (self Message) GasPrice() *big.Int { return self.price }
   174  func (self Message) Gas() *big.Int      { return self.gas }
   175  func (self Message) Value() *big.Int    { return self.value }
   176  func (self Message) Nonce() uint64      { return 0 }
   177  func (self Message) Data() []byte       { return self.data }