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  }