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