closure.go 2.7 KB

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