| 
									
										
										
										
											2014-10-18 13:31:20 +02:00
										 |  |  | package vm | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2014-12-30 16:16:02 +01:00
										 |  |  | 	"math" | 
					
						
							| 
									
										
										
										
											2014-08-11 16:23:38 +02:00
										 |  |  | 	"math/big" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-30 16:16:02 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/ethutil" | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-02 16:14:12 +01:00
										 |  |  | type ContextRef interface { | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 	ReturnGas(*big.Int, *big.Int) | 
					
						
							|  |  |  | 	Address() []byte | 
					
						
							| 
									
										
										
										
											2014-12-03 17:06:54 +01:00
										 |  |  | 	SetCode([]byte) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-02 16:14:12 +01:00
										 |  |  | type Context struct { | 
					
						
							| 
									
										
										
										
											2015-01-03 17:29:08 +01:00
										 |  |  | 	caller ContextRef | 
					
						
							|  |  |  | 	object ContextRef | 
					
						
							|  |  |  | 	Code   []byte | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Gas, UsedGas, Price *big.Int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Args []byte | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-02 16:14:12 +01:00
										 |  |  | // Create a new context for the given data items | 
					
						
							| 
									
										
										
										
											2015-01-03 17:29:08 +01:00
										 |  |  | func NewContext(caller ContextRef, object ContextRef, code []byte, gas, price *big.Int) *Context { | 
					
						
							|  |  |  | 	c := &Context{caller: caller, object: object, Code: code, Args: nil} | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Gas should be a pointer so it can safely be reduced through the run | 
					
						
							|  |  |  | 	// This pointer will be off the state transition | 
					
						
							|  |  |  | 	c.Gas = gas //new(big.Int).Set(gas) | 
					
						
							|  |  |  | 	// In most cases price and value are pointers to transaction objects | 
					
						
							|  |  |  | 	// and we don't want the transaction's values to change. | 
					
						
							|  |  |  | 	c.Price = new(big.Int).Set(price) | 
					
						
							|  |  |  | 	c.UsedGas = new(big.Int) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return c | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-04 14:20:16 +01:00
										 |  |  | func (c *Context) GetOp(n uint64) OpCode { | 
					
						
							|  |  |  | 	return OpCode(c.GetByte(n)) | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-04 14:20:16 +01:00
										 |  |  | func (c *Context) GetByte(n uint64) byte { | 
					
						
							|  |  |  | 	if n < uint64(len(c.Code)) { | 
					
						
							|  |  |  | 		return c.Code[n] | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-02 16:14:12 +01:00
										 |  |  | func (c *Context) GetBytes(x, y int) []byte { | 
					
						
							| 
									
										
										
										
											2014-12-30 16:16:02 +01:00
										 |  |  | 	return c.GetRangeValue(uint64(x), uint64(y)) | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-02 16:14:12 +01:00
										 |  |  | func (c *Context) GetRangeValue(x, size uint64) []byte { | 
					
						
							| 
									
										
										
										
											2014-12-30 16:16:02 +01:00
										 |  |  | 	x = uint64(math.Min(float64(x), float64(len(c.Code)))) | 
					
						
							|  |  |  | 	y := uint64(math.Min(float64(x+size), float64(len(c.Code)))) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-30 16:16:02 +01:00
										 |  |  | 	return ethutil.LeftPadBytes(c.Code[x:y], int(size)) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-12 13:49:47 +01:00
										 |  |  | func (c *Context) GetCode(x, size uint64) []byte { | 
					
						
							|  |  |  | 	x = uint64(math.Min(float64(x), float64(len(c.Code)))) | 
					
						
							|  |  |  | 	y := uint64(math.Min(float64(x+size), float64(len(c.Code)))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ethutil.RightPadBytes(c.Code[x:y], int(size)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-02 16:14:12 +01:00
										 |  |  | func (c *Context) Return(ret []byte) []byte { | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 	// Return the remaining gas to the caller | 
					
						
							|  |  |  | 	c.caller.ReturnGas(c.Gas, c.Price) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-03 17:35:57 +01:00
										 |  |  | /* | 
					
						
							|  |  |  |  * Gas functions | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-01-02 16:14:12 +01:00
										 |  |  | func (c *Context) UseGas(gas *big.Int) bool { | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 	if c.Gas.Cmp(gas) < 0 { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Sub the amount of gas from the remaining | 
					
						
							|  |  |  | 	c.Gas.Sub(c.Gas, gas) | 
					
						
							|  |  |  | 	c.UsedGas.Add(c.UsedGas, gas) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Implement the caller interface | 
					
						
							| 
									
										
										
										
											2015-01-02 16:14:12 +01:00
										 |  |  | func (c *Context) ReturnGas(gas, price *big.Int) { | 
					
						
							|  |  |  | 	// Return the gas to the context | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 	c.Gas.Add(c.Gas, gas) | 
					
						
							|  |  |  | 	c.UsedGas.Sub(c.UsedGas, gas) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-03 17:35:57 +01:00
										 |  |  | /* | 
					
						
							|  |  |  |  * Set / Get | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-01-02 16:14:12 +01:00
										 |  |  | func (c *Context) Address() []byte { | 
					
						
							| 
									
										
										
										
											2014-12-03 17:35:57 +01:00
										 |  |  | 	return c.object.Address() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-02 16:14:12 +01:00
										 |  |  | func (self *Context) SetCode(code []byte) { | 
					
						
							| 
									
										
										
										
											2014-12-03 17:35:57 +01:00
										 |  |  | 	self.Code = code | 
					
						
							|  |  |  | } |