vm.go 5.9 KB

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