closure.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package vm
  2. // TODO Re write VM to use values instead of big integers?
  3. import (
  4. "math/big"
  5. "github.com/ethereum/go-ethereum/ethutil"
  6. "github.com/ethereum/go-ethereum/state"
  7. )
  8. type ClosureRef interface {
  9. ReturnGas(*big.Int, *big.Int)
  10. Address() []byte
  11. Object() *state.StateObject
  12. GetStorage(*big.Int) *ethutil.Value
  13. SetStorage(*big.Int, *ethutil.Value)
  14. }
  15. // Basic inline closure object which implement the 'closure' interface
  16. type Closure struct {
  17. caller ClosureRef
  18. object *state.StateObject
  19. Code []byte
  20. message *state.Message
  21. exe *Execution
  22. Gas, UsedGas, Price *big.Int
  23. Args []byte
  24. }
  25. // Create a new closure for the given data items
  26. func NewClosure(msg *state.Message, caller ClosureRef, object *state.StateObject, code []byte, gas, price *big.Int) *Closure {
  27. c := &Closure{message: msg, caller: caller, object: object, Code: code, Args: nil}
  28. // Gas should be a pointer so it can safely be reduced through the run
  29. // This pointer will be off the state transition
  30. c.Gas = gas //new(big.Int).Set(gas)
  31. // In most cases price and value are pointers to transaction objects
  32. // and we don't want the transaction's values to change.
  33. c.Price = new(big.Int).Set(price)
  34. c.UsedGas = new(big.Int)
  35. return c
  36. }
  37. // Retuns the x element in data slice
  38. func (c *Closure) GetStorage(x *big.Int) *ethutil.Value {
  39. m := c.object.GetStorage(x)
  40. if m == nil {
  41. return ethutil.EmptyValue()
  42. }
  43. return m
  44. }
  45. func (c *Closure) Get(x *big.Int) *ethutil.Value {
  46. return c.Gets(x, big.NewInt(1))
  47. }
  48. func (c *Closure) GetOp(x int) OpCode {
  49. return OpCode(c.GetByte(x))
  50. }
  51. func (c *Closure) GetByte(x int) byte {
  52. if x > -1 && x < len(c.Code) {
  53. return c.Code[x]
  54. }
  55. return 0
  56. }
  57. func (c *Closure) GetBytes(x, y int) []byte {
  58. if x >= len(c.Code) || y >= len(c.Code) {
  59. return nil
  60. }
  61. return c.Code[x : x+y]
  62. }
  63. func (c *Closure) Gets(x, y *big.Int) *ethutil.Value {
  64. if x.Int64() >= int64(len(c.Code)) || y.Int64() >= int64(len(c.Code)) {
  65. return ethutil.NewValue(0)
  66. }
  67. partial := c.Code[x.Int64() : x.Int64()+y.Int64()]
  68. return ethutil.NewValue(partial)
  69. }
  70. func (c *Closure) SetStorage(x *big.Int, val *ethutil.Value) {
  71. c.object.SetStorage(x, val)
  72. }
  73. func (c *Closure) Address() []byte {
  74. return c.object.Address()
  75. }
  76. func (c *Closure) Call(vm VirtualMachine, args []byte) ([]byte, *big.Int, error) {
  77. c.Args = args
  78. ret, err := vm.RunClosure(c)
  79. return ret, c.UsedGas, err
  80. }
  81. func (c *Closure) Return(ret []byte) []byte {
  82. // Return the remaining gas to the caller
  83. c.caller.ReturnGas(c.Gas, c.Price)
  84. return ret
  85. }
  86. func (c *Closure) UseGas(gas *big.Int) bool {
  87. if c.Gas.Cmp(gas) < 0 {
  88. return false
  89. }
  90. // Sub the amount of gas from the remaining
  91. c.Gas.Sub(c.Gas, gas)
  92. c.UsedGas.Add(c.UsedGas, gas)
  93. return true
  94. }
  95. // Implement the caller interface
  96. func (c *Closure) ReturnGas(gas, price *big.Int) {
  97. // Return the gas to the closure
  98. c.Gas.Add(c.Gas, gas)
  99. c.UsedGas.Sub(c.UsedGas, gas)
  100. }
  101. func (c *Closure) Object() *state.StateObject {
  102. return c.object
  103. }
  104. func (c *Closure) Caller() ClosureRef {
  105. return c.caller
  106. }
  107. func (self *Closure) SetExecution(exe *Execution) {
  108. self.exe = exe
  109. }