| 
									
										
										
										
											2014-10-18 13:31:20 +02:00
										 |  |  | package vm | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"math/big" | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2015-03-23 16:59:09 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/state" | 
					
						
							| 
									
										
										
										
											2015-03-23 21:48:31 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | // Vm implements VirtualMachine | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | type Vm struct { | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	env Environment | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err error | 
					
						
							| 
									
										
										
										
											2015-02-28 20:14:01 +01:00
										 |  |  | 	// For logging | 
					
						
							|  |  |  | 	debug bool | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	BreakPoints []int64 | 
					
						
							|  |  |  | 	Stepping    bool | 
					
						
							|  |  |  | 	Fn          string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Recoverable bool | 
					
						
							| 
									
										
										
										
											2015-03-28 20:03:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Will be called before the vm returns | 
					
						
							|  |  |  | 	After func(*Context, error) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | // New returns a new Virtual Machine | 
					
						
							| 
									
										
										
										
											2015-01-20 15:49:12 +01:00
										 |  |  | func New(env Environment) *Vm { | 
					
						
							| 
									
										
										
										
											2015-06-10 12:23:49 +02:00
										 |  |  | 	return &Vm{env: env, debug: Debug, Recoverable: true} | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | // Run loops and evaluates the contract's code with the given input data | 
					
						
							|  |  |  | func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) { | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	self.env.SetDepth(self.env.Depth() + 1) | 
					
						
							| 
									
										
										
										
											2015-03-23 21:48:31 +01:00
										 |  |  | 	defer self.env.SetDepth(self.env.Depth() - 1) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 13:44:15 +01:00
										 |  |  | 	var ( | 
					
						
							|  |  |  | 		caller = context.caller | 
					
						
							|  |  |  | 		code   = context.Code | 
					
						
							|  |  |  | 		value  = context.value | 
					
						
							|  |  |  | 		price  = context.Price | 
					
						
							| 
									
										
										
										
											2015-06-12 13:35:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		op       OpCode                  // current opcode | 
					
						
							|  |  |  | 		codehash = crypto.Sha3Hash(code) // codehash is used when doing jump dest caching | 
					
						
							|  |  |  | 		mem      = NewMemory()           // bound memory | 
					
						
							|  |  |  | 		stack    = newstack()            // local stack | 
					
						
							|  |  |  | 		statedb  = self.env.State()      // current state | 
					
						
							|  |  |  | 		// For optimisation reason we're using uint64 as the program counter. | 
					
						
							|  |  |  | 		// It's theoretically possible to go above 2^64. The YP defines the PC to be uint256. Pratically much less so feasible. | 
					
						
							|  |  |  | 		pc = uint64(0) // program counter | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// jump evaluates and checks whether the given jump destination is a valid one | 
					
						
							|  |  |  | 		// if valid move the `pc` otherwise return an error. | 
					
						
							|  |  |  | 		jump = func(from uint64, to *big.Int) error { | 
					
						
							|  |  |  | 			if !context.jumpdests.has(codehash, code, to) { | 
					
						
							|  |  |  | 				nop := context.GetOp(to.Uint64()) | 
					
						
							|  |  |  | 				return fmt.Errorf("invalid jump destination (%v) %v", nop, to) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			pc = to.Uint64() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		newMemSize *big.Int | 
					
						
							|  |  |  | 		cost       *big.Int | 
					
						
							| 
									
										
										
										
											2015-03-13 13:44:15 +01:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-27 16:53:05 +01:00
										 |  |  | 	// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return. | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 	defer func() { | 
					
						
							| 
									
										
										
										
											2015-03-28 20:03:25 +01:00
										 |  |  | 		if self.After != nil { | 
					
						
							|  |  |  | 			self.After(context, err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2015-06-12 13:35:14 +02:00
										 |  |  | 			self.log(pc, op, context.Gas, cost, mem, stack, context, err) | 
					
						
							| 
									
										
										
										
											2015-06-10 12:23:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 			// In case of a VM exception (known exceptions) all gas consumed (panics NOT included). | 
					
						
							|  |  |  | 			context.UseGas(context.Gas) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			ret = context.Return(nil) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-17 11:19:23 +01:00
										 |  |  | 	if context.CodeAddr != nil { | 
					
						
							|  |  |  | 		if p := Precompiled[context.CodeAddr.Str()]; p != nil { | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | 			return self.RunPrecompiled(p, input, context) | 
					
						
							| 
									
										
										
										
											2015-03-17 11:19:23 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-29 14:58:57 +02:00
										 |  |  | 	// Don't bother with the execution if there's no code. | 
					
						
							|  |  |  | 	if len(code) == 0 { | 
					
						
							|  |  |  | 		return context.Return(nil), nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	for { | 
					
						
							|  |  |  | 		// The base for all big integer arithmetic | 
					
						
							|  |  |  | 		base := new(big.Int) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Get the memory location of pc | 
					
						
							|  |  |  | 		op = context.GetOp(pc) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | 		// calculate the new memory size and gas price for the current executing opcode | 
					
						
							| 
									
										
										
										
											2015-06-12 13:35:14 +02:00
										 |  |  | 		newMemSize, cost, err = self.calculateGasAndSize(context, caller, op, statedb, mem, stack) | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | 		// Use the calculated gas. When insufficient gas is present, use all gas and return an | 
					
						
							|  |  |  | 		// Out Of Gas error | 
					
						
							| 
									
										
										
										
											2015-06-12 13:35:14 +02:00
										 |  |  | 		if !context.UseGas(cost) { | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			context.UseGas(context.Gas) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-12 13:35:14 +02:00
										 |  |  | 			return context.Return(nil), OutOfGasError{} | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | 		// Resize the memory calculated previously | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		mem.Resize(newMemSize.Uint64()) | 
					
						
							| 
									
										
										
										
											2015-06-12 13:35:14 +02:00
										 |  |  | 		// Add a log message | 
					
						
							|  |  |  | 		self.log(pc, op, context.Gas, cost, mem, stack, context, nil) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		switch op { | 
					
						
							|  |  |  | 		case ADD: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			base.Add(x, y) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			U256(base) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			// pop result back on the stack | 
					
						
							|  |  |  | 			stack.push(base) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case SUB: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			base.Sub(x, y) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			U256(base) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			// pop result back on the stack | 
					
						
							|  |  |  | 			stack.push(base) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case MUL: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			base.Mul(x, y) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			U256(base) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			// pop result back on the stack | 
					
						
							|  |  |  | 			stack.push(base) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case DIV: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 			if y.Cmp(common.Big0) != 0 { | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 				base.Div(x, y) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			U256(base) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			// pop result back on the stack | 
					
						
							|  |  |  | 			stack.push(base) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case SDIV: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := S256(stack.pop()), S256(stack.pop()) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 			if y.Cmp(common.Big0) == 0 { | 
					
						
							|  |  |  | 				base.Set(common.Big0) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				n := new(big.Int) | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				if new(big.Int).Mul(x, y).Cmp(common.Big0) < 0 { | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 					n.SetInt64(-1) | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					n.SetInt64(1) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				base.Div(x.Abs(x), y.Abs(y)).Mul(base, n) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				U256(base) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(base) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case MOD: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 			if y.Cmp(common.Big0) == 0 { | 
					
						
							|  |  |  | 				base.Set(common.Big0) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				base.Mod(x, y) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			U256(base) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(base) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case SMOD: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := S256(stack.pop()), S256(stack.pop()) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 			if y.Cmp(common.Big0) == 0 { | 
					
						
							|  |  |  | 				base.Set(common.Big0) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				n := new(big.Int) | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				if x.Cmp(common.Big0) < 0 { | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 					n.SetInt64(-1) | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					n.SetInt64(1) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				base.Mod(x.Abs(x), y.Abs(y)).Mul(base, n) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				U256(base) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(base) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case EXP: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			base.Exp(x, y, Pow256) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			U256(base) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(base) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case SIGNEXTEND: | 
					
						
							| 
									
										
										
										
											2015-03-12 19:41:56 +01:00
										 |  |  | 			back := stack.pop() | 
					
						
							|  |  |  | 			if back.Cmp(big.NewInt(31)) < 0 { | 
					
						
							|  |  |  | 				bit := uint(back.Uint64()*8 + 7) | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 				num := stack.pop() | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				mask := new(big.Int).Lsh(common.Big1, bit) | 
					
						
							|  |  |  | 				mask.Sub(mask, common.Big1) | 
					
						
							|  |  |  | 				if common.BitTest(num, int(bit)) { | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 					num.Or(num, mask.Not(mask)) | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					num.And(num, mask) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				num = U256(num) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 				stack.push(num) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		case NOT: | 
					
						
							| 
									
										
										
										
											2015-03-12 18:22:35 +01:00
										 |  |  | 			stack.push(U256(new(big.Int).Not(stack.pop()))) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case LT: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-06-10 12:23:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			// x < y | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			if x.Cmp(y) < 0 { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.BigTrue) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.BigFalse) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		case GT: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// x > y | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			if x.Cmp(y) > 0 { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.BigTrue) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.BigFalse) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case SLT: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := S256(stack.pop()), S256(stack.pop()) | 
					
						
							| 
									
										
										
										
											2015-06-10 12:23:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			// x < y | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			if x.Cmp(S256(y)) < 0 { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.BigTrue) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.BigFalse) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		case SGT: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := S256(stack.pop()), S256(stack.pop()) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// x > y | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			if x.Cmp(y) > 0 { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.BigTrue) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.BigFalse) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case EQ: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// x == y | 
					
						
							|  |  |  | 			if x.Cmp(y) == 0 { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.BigTrue) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.BigFalse) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		case ISZERO: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x := stack.pop() | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 			if x.Cmp(common.BigFalse) > 0 { | 
					
						
							|  |  |  | 				stack.push(common.BigFalse) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.BigTrue) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case AND: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(base.And(x, y)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case OR: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(base.Or(x, y)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case XOR: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x, y := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(base.Xor(x, y)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case BYTE: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			th, val := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if th.Cmp(big.NewInt(32)) < 0 { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				byt := big.NewInt(int64(common.LeftPadBytes(val.Bytes(), 32)[th.Int64()])) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				base.Set(byt) | 
					
						
							|  |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				base.Set(common.BigFalse) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(base) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case ADDMOD: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x := stack.pop() | 
					
						
							|  |  |  | 			y := stack.pop() | 
					
						
							|  |  |  | 			z := stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-12 18:22:35 +01:00
										 |  |  | 			if z.Cmp(Zero) > 0 { | 
					
						
							| 
									
										
										
										
											2015-03-13 13:44:15 +01:00
										 |  |  | 				add := new(big.Int).Add(x, y) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 				base.Mod(add, z) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-12 18:22:35 +01:00
										 |  |  | 				base = U256(base) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(base) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case MULMOD: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			x := stack.pop() | 
					
						
							|  |  |  | 			y := stack.pop() | 
					
						
							|  |  |  | 			z := stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 13:44:15 +01:00
										 |  |  | 			if z.Cmp(Zero) > 0 { | 
					
						
							|  |  |  | 				mul := new(big.Int).Mul(x, y) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 				base.Mod(mul, z) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				U256(base) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(base) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case SHA3: | 
					
						
							| 
									
										
										
										
											2015-03-12 23:26:58 +01:00
										 |  |  | 			offset, size := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			data := crypto.Sha3(mem.Get(offset.Int64(), size.Int64())) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 			stack.push(common.BigD(data)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case ADDRESS: | 
					
						
							| 
									
										
										
										
											2015-03-16 18:42:18 +01:00
										 |  |  | 			stack.push(common.Bytes2Big(context.Address().Bytes())) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case BALANCE: | 
					
						
							| 
									
										
										
										
											2015-03-16 18:42:18 +01:00
										 |  |  | 			addr := common.BigToAddress(stack.pop()) | 
					
						
							| 
									
										
										
										
											2015-03-12 22:29:10 +01:00
										 |  |  | 			balance := statedb.GetBalance(addr) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(balance) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case ORIGIN: | 
					
						
							|  |  |  | 			origin := self.env.Origin() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 18:42:18 +01:00
										 |  |  | 			stack.push(origin.Big()) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case CALLER: | 
					
						
							|  |  |  | 			caller := context.caller.Address() | 
					
						
							| 
									
										
										
										
											2015-03-16 18:42:18 +01:00
										 |  |  | 			stack.push(common.Bytes2Big(caller.Bytes())) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case CALLVALUE: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(value) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case CALLDATALOAD: | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | 			data := getData(input, stack.pop(), common.Big32) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-28 20:30:16 +01:00
										 |  |  | 			stack.push(common.Bytes2Big(data)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case CALLDATASIZE: | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | 			l := int64(len(input)) | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(big.NewInt(l)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case CALLDATACOPY: | 
					
						
							|  |  |  | 			var ( | 
					
						
							| 
									
										
										
										
											2015-03-19 15:06:56 +01:00
										 |  |  | 				mOff = stack.pop() | 
					
						
							|  |  |  | 				cOff = stack.pop() | 
					
						
							|  |  |  | 				l    = stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			) | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | 			data := getData(input, cOff, l) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-19 15:06:56 +01:00
										 |  |  | 			mem.Set(mOff.Uint64(), l.Uint64(), data) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case CODESIZE, EXTCODESIZE: | 
					
						
							|  |  |  | 			var code []byte | 
					
						
							|  |  |  | 			if op == EXTCODESIZE { | 
					
						
							| 
									
										
										
										
											2015-03-16 18:42:18 +01:00
										 |  |  | 				addr := common.BigToAddress(stack.pop()) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				code = statedb.GetCode(addr) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				code = context.Code | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			l := big.NewInt(int64(len(code))) | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(l) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case CODECOPY, EXTCODECOPY: | 
					
						
							|  |  |  | 			var code []byte | 
					
						
							|  |  |  | 			if op == EXTCODECOPY { | 
					
						
							| 
									
										
										
										
											2015-03-16 18:42:18 +01:00
										 |  |  | 				addr := common.BigToAddress(stack.pop()) | 
					
						
							|  |  |  | 				code = statedb.GetCode(addr) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				code = context.Code | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-03-19 15:06:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			var ( | 
					
						
							| 
									
										
										
										
											2015-03-19 15:06:56 +01:00
										 |  |  | 				mOff = stack.pop() | 
					
						
							|  |  |  | 				cOff = stack.pop() | 
					
						
							|  |  |  | 				l    = stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-19 22:45:03 +01:00
										 |  |  | 			codeCopy := getData(code, cOff, l) | 
					
						
							| 
									
										
										
										
											2015-03-19 15:06:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			mem.Set(mOff.Uint64(), l.Uint64(), codeCopy) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case GASPRICE: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(context.Price) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case BLOCKHASH: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			num := stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 			n := new(big.Int).Sub(self.env.BlockNumber(), common.Big257) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			if num.Cmp(n) > 0 && num.Cmp(self.env.BlockNumber()) < 0 { | 
					
						
							| 
									
										
										
										
											2015-03-17 11:19:23 +01:00
										 |  |  | 				stack.push(self.env.GetHash(num.Uint64()).Big()) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.Big0) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case COINBASE: | 
					
						
							|  |  |  | 			coinbase := self.env.Coinbase() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-17 11:19:23 +01:00
										 |  |  | 			stack.push(coinbase.Big()) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case TIMESTAMP: | 
					
						
							|  |  |  | 			time := self.env.Time() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(big.NewInt(time)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case NUMBER: | 
					
						
							|  |  |  | 			number := self.env.BlockNumber() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(U256(number)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case DIFFICULTY: | 
					
						
							|  |  |  | 			difficulty := self.env.Difficulty() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(difficulty) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case GASLIMIT: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(self.env.GasLimit()) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32: | 
					
						
							| 
									
										
										
										
											2015-06-10 10:44:46 +02:00
										 |  |  | 			size := uint64(op - PUSH1 + 1) | 
					
						
							|  |  |  | 			byts := getData(code, new(big.Int).SetUint64(pc+1), new(big.Int).SetUint64(size)) | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			// push value to stack | 
					
						
							| 
									
										
										
										
											2015-03-28 20:30:16 +01:00
										 |  |  | 			stack.push(common.Bytes2Big(byts)) | 
					
						
							| 
									
										
										
										
											2015-06-10 10:44:46 +02:00
										 |  |  | 			pc += size | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case POP: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16: | 
					
						
							|  |  |  | 			n := int(op - DUP1 + 1) | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.dup(n) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16: | 
					
						
							|  |  |  | 			n := int(op - SWAP1 + 2) | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.swap(n) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case LOG0, LOG1, LOG2, LOG3, LOG4: | 
					
						
							|  |  |  | 			n := int(op - LOG0) | 
					
						
							| 
									
										
										
										
											2015-03-16 23:10:26 +01:00
										 |  |  | 			topics := make([]common.Hash, n) | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			mStart, mSize := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			for i := 0; i < n; i++ { | 
					
						
							| 
									
										
										
										
											2015-05-26 12:42:33 +02:00
										 |  |  | 				topics[i] = common.BigToHash(stack.pop()) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			data := mem.Get(mStart.Int64(), mSize.Int64()) | 
					
						
							| 
									
										
										
										
											2015-04-08 17:14:58 +02:00
										 |  |  | 			log := state.NewLog(context.Address(), topics, data, self.env.BlockNumber().Uint64()) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			self.env.AddLog(log) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case MLOAD: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			offset := stack.pop() | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 			val := common.BigD(mem.Get(offset.Int64(), 32)) | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(val) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-26 12:42:33 +02:00
										 |  |  | 		case MSTORE: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			// pop value of the stack | 
					
						
							|  |  |  | 			mStart, val := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 			mem.Set(mStart.Uint64(), 32, common.BigToBytes(val, 256)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case MSTORE8: | 
					
						
							| 
									
										
										
										
											2015-03-19 22:45:03 +01:00
										 |  |  | 			off, val := stack.pop().Int64(), stack.pop().Int64() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-19 22:45:03 +01:00
										 |  |  | 			mem.store[off] = byte(val & 0xff) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case SLOAD: | 
					
						
							| 
									
										
										
										
											2015-03-16 18:42:18 +01:00
										 |  |  | 			loc := common.BigToHash(stack.pop()) | 
					
						
							|  |  |  | 			val := common.Bytes2Big(statedb.GetState(context.Address(), loc)) | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(val) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case SSTORE: | 
					
						
							| 
									
										
										
										
											2015-03-16 18:42:18 +01:00
										 |  |  | 			loc := common.BigToHash(stack.pop()) | 
					
						
							|  |  |  | 			val := stack.pop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			statedb.SetState(context.Address(), loc, val) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case JUMP: | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 			if err := jump(pc, stack.pop()); err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		case JUMPI: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			pos, cond := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 			if cond.Cmp(common.BigTrue) >= 0 { | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 				if err := jump(pc, pos); err != nil { | 
					
						
							|  |  |  | 					return nil, err | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case JUMPDEST: | 
					
						
							|  |  |  | 		case PC: | 
					
						
							| 
									
										
										
										
											2015-06-10 10:44:46 +02:00
										 |  |  | 			stack.push(new(big.Int).SetUint64(pc)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case MSIZE: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(big.NewInt(int64(mem.Len()))) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case GAS: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			stack.push(context.Gas) | 
					
						
							| 
									
										
										
										
											2015-02-04 07:39:02 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case CREATE: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var ( | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 				value        = stack.pop() | 
					
						
							|  |  |  | 				offset, size = stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 				input        = mem.Get(offset.Int64(), size.Int64()) | 
					
						
							|  |  |  | 				gas          = new(big.Int).Set(context.Gas) | 
					
						
							| 
									
										
										
										
											2015-03-16 18:42:18 +01:00
										 |  |  | 				addr         common.Address | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			context.UseGas(context.Gas) | 
					
						
							| 
									
										
										
										
											2015-03-24 15:23:16 +01:00
										 |  |  | 			ret, suberr, ref := self.env.Create(context, input, gas, price, value) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			if suberr != nil { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.BigFalse) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				// gas < len(ret) * CreateDataGas == NO_CODE | 
					
						
							|  |  |  | 				dataGas := big.NewInt(int64(len(ret))) | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 				dataGas.Mul(dataGas, params.CreateDataGas) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 				if context.UseGas(dataGas) { | 
					
						
							|  |  |  | 					ref.SetCode(ret) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				addr = ref.Address() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 18:42:18 +01:00
										 |  |  | 				stack.push(addr.Big()) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case CALL, CALLCODE: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			gas := stack.pop() | 
					
						
							|  |  |  | 			// pop gas and value of the stack. | 
					
						
							|  |  |  | 			addr, value := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-02-19 11:09:46 +01:00
										 |  |  | 			value = U256(value) | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			// pop input size and offset | 
					
						
							|  |  |  | 			inOffset, inSize := stack.pop(), stack.pop() | 
					
						
							|  |  |  | 			// pop return size and offset | 
					
						
							|  |  |  | 			retOffset, retSize := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 18:42:18 +01:00
										 |  |  | 			address := common.BigToAddress(addr) | 
					
						
							| 
									
										
										
										
											2015-02-02 20:01:10 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			// Get the arguments from the memory | 
					
						
							|  |  |  | 			args := mem.Get(inOffset.Int64(), inSize.Int64()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-03 11:56:43 +01:00
										 |  |  | 			if len(value.Bytes()) > 0 { | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 				gas.Add(gas, params.CallStipend) | 
					
						
							| 
									
										
										
										
											2015-03-03 11:56:43 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			var ( | 
					
						
							|  |  |  | 				ret []byte | 
					
						
							|  |  |  | 				err error | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 			if op == CALLCODE { | 
					
						
							| 
									
										
										
										
											2015-02-02 20:01:10 -08:00
										 |  |  | 				ret, err = self.env.CallCode(context, address, args, gas, price, value) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2015-02-02 20:01:10 -08:00
										 |  |  | 				ret, err = self.env.Call(context, address, args, gas, price, value) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.BigFalse) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 				stack.push(common.BigTrue) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				mem.Set(retOffset.Uint64(), retSize.Uint64(), ret) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-06-10 12:23:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		case RETURN: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 			offset, size := stack.pop(), stack.pop() | 
					
						
							| 
									
										
										
										
											2015-05-19 17:26:38 +02:00
										 |  |  | 			ret := mem.GetPtr(offset.Int64(), size.Int64()) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			return context.Return(ret), nil | 
					
						
							|  |  |  | 		case SUICIDE: | 
					
						
							| 
									
										
										
										
											2015-03-16 18:42:18 +01:00
										 |  |  | 			receiver := statedb.GetOrNewStateObject(common.BigToAddress(stack.pop())) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			balance := statedb.GetBalance(context.Address()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-26 18:39:05 +01:00
										 |  |  | 			receiver.AddBalance(balance) | 
					
						
							| 
									
										
										
										
											2015-03-09 11:28:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 			statedb.Delete(context.Address()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			fallthrough | 
					
						
							|  |  |  | 		case STOP: // Stop the context | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return context.Return(nil), nil | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 			return nil, fmt.Errorf("Invalid opcode %x", op) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-10 10:44:46 +02:00
										 |  |  | 		pc++ | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | // calculateGasAndSize calculates the required given the opcode and stack items calculates the new memorysize for | 
					
						
							|  |  |  | // the operation. This does not reduce gas or resizes the memory. | 
					
						
							| 
									
										
										
										
											2015-06-10 17:45:21 +02:00
										 |  |  | func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCode, statedb *state.StateDB, mem *Memory, stack *stack) (*big.Int, *big.Int, error) { | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 	var ( | 
					
						
							|  |  |  | 		gas                 = new(big.Int) | 
					
						
							|  |  |  | 		newMemSize *big.Int = new(big.Int) | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 	err := baseCheck(op, stack, gas) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 	// stack Check, memory resize & gas phase | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	switch op { | 
					
						
							|  |  |  | 	case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16: | 
					
						
							|  |  |  | 		n := int(op - SWAP1 + 2) | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 		err := stack.require(n) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-03-03 11:11:11 +01:00
										 |  |  | 		gas.Set(GasFastestStep) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16: | 
					
						
							|  |  |  | 		n := int(op - DUP1 + 1) | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 		err := stack.require(n) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-03-03 11:11:11 +01:00
										 |  |  | 		gas.Set(GasFastestStep) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	case LOG0, LOG1, LOG2, LOG3, LOG4: | 
					
						
							|  |  |  | 		n := int(op - LOG0) | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 		err := stack.require(n + 2) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1] | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 		gas.Add(gas, params.LogGas) | 
					
						
							|  |  |  | 		gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), params.LogTopicGas)) | 
					
						
							|  |  |  | 		gas.Add(gas, new(big.Int).Mul(mSize, params.LogDataGas)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		newMemSize = calcMemSize(mStart, mSize) | 
					
						
							|  |  |  | 	case EXP: | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 		gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), params.ExpByteGas)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	case SSTORE: | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 		err := stack.require(2) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 		var g *big.Int | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		y, x := stack.data[stack.len()-2], stack.data[stack.len()-1] | 
					
						
							| 
									
										
										
										
											2015-03-16 18:42:18 +01:00
										 |  |  | 		val := statedb.GetState(context.Address(), common.BigToHash(x)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		if len(val) == 0 && len(y.Bytes()) > 0 { | 
					
						
							|  |  |  | 			// 0 => non 0 | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 			g = params.SstoreSetGas | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		} else if len(val) > 0 && len(y.Bytes()) == 0 { | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 			statedb.Refund(self.env.Origin(), params.SstoreRefundGas) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 			g = params.SstoreClearGas | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			// non 0 => non 0 (or 0 => 0) | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 			g = params.SstoreClearGas | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 		gas.Set(g) | 
					
						
							| 
									
										
										
										
											2015-03-09 11:28:35 +01:00
										 |  |  | 	case SUICIDE: | 
					
						
							|  |  |  | 		if !statedb.IsDeleted(context.Address()) { | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 			statedb.Refund(self.env.Origin(), params.SuicideRefundGas) | 
					
						
							| 
									
										
										
										
											2015-03-09 11:28:35 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	case MLOAD: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		newMemSize = calcMemSize(stack.peek(), u256(32)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	case MSTORE8: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		newMemSize = calcMemSize(stack.peek(), u256(1)) | 
					
						
							| 
									
										
										
										
											2015-03-02 17:55:45 +01:00
										 |  |  | 	case MSTORE: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		newMemSize = calcMemSize(stack.peek(), u256(32)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	case RETURN: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2]) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	case SHA3: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2]) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		words := toWordSize(stack.data[stack.len()-2]) | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 		gas.Add(gas, words.Mul(words, params.Sha3WordGas)) | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 	case CALLDATACOPY: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3]) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		words := toWordSize(stack.data[stack.len()-3]) | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 		gas.Add(gas, words.Mul(words, params.CopyGas)) | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 	case CODECOPY: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3]) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		words := toWordSize(stack.data[stack.len()-3]) | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 		gas.Add(gas, words.Mul(words, params.CopyGas)) | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 	case EXTCODECOPY: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4]) | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		words := toWordSize(stack.data[stack.len()-4]) | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 		gas.Add(gas, words.Mul(words, params.CopyGas)) | 
					
						
							| 
									
										
										
										
											2015-03-03 13:29:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 	case CREATE: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3]) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	case CALL, CALLCODE: | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		gas.Add(gas, stack.data[stack.len()-1]) | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if op == CALL { | 
					
						
							| 
									
										
										
										
											2015-03-16 18:42:18 +01:00
										 |  |  | 			if self.env.State().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil { | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 				gas.Add(gas, params.CallNewAccountGas) | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-03-03 13:29:52 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		if len(stack.data[stack.len()-3].Bytes()) > 0 { | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 			gas.Add(gas, params.CallValueTransferGas) | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-10 00:25:27 +01:00
										 |  |  | 		x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7]) | 
					
						
							|  |  |  | 		y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5]) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 		newMemSize = common.BigMax(x, y) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	if newMemSize.Cmp(common.Big0) > 0 { | 
					
						
							| 
									
										
										
										
											2015-03-03 11:56:43 +01:00
										 |  |  | 		newMemSizeWords := toWordSize(newMemSize) | 
					
						
							|  |  |  | 		newMemSize.Mul(newMemSizeWords, u256(32)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 { | 
					
						
							| 
									
										
										
										
											2015-03-03 11:11:11 +01:00
										 |  |  | 			oldSize := toWordSize(big.NewInt(int64(mem.Len()))) | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 			pow := new(big.Int).Exp(oldSize, common.Big2, Zero) | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 			linCoef := new(big.Int).Mul(oldSize, params.MemoryGas) | 
					
						
							|  |  |  | 			quadCoef := new(big.Int).Div(pow, params.QuadCoeffDiv) | 
					
						
							| 
									
										
										
										
											2015-03-03 11:11:11 +01:00
										 |  |  | 			oldTotalFee := new(big.Int).Add(linCoef, quadCoef) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 			pow.Exp(newMemSizeWords, common.Big2, Zero) | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 			linCoef = new(big.Int).Mul(newMemSizeWords, params.MemoryGas) | 
					
						
							|  |  |  | 			quadCoef = new(big.Int).Div(pow, params.QuadCoeffDiv) | 
					
						
							| 
									
										
										
										
											2015-03-03 11:11:11 +01:00
										 |  |  | 			newTotalFee := new(big.Int).Add(linCoef, quadCoef) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-01 10:53:32 +02:00
										 |  |  | 			fee := new(big.Int).Sub(newTotalFee, oldTotalFee) | 
					
						
							|  |  |  | 			gas.Add(gas, fee) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-27 16:09:57 +01:00
										 |  |  | 	return newMemSize, gas, nil | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | // RunPrecompile runs and evaluate the output of a precompiled contract defined in contracts.go | 
					
						
							|  |  |  | func (self *Vm) RunPrecompiled(p *PrecompiledAccount, input []byte, context *Context) (ret []byte, err error) { | 
					
						
							|  |  |  | 	gas := p.Gas(len(input)) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	if context.UseGas(gas) { | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | 		ret = p.Call(input) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return context.Return(ret), nil | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2015-06-12 13:35:14 +02:00
										 |  |  | 		return nil, OutOfGasError{} | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | // log emits a log event to the environment for each opcode encountered. This is not to be confused with the | 
					
						
							|  |  |  | // LOG* opcode. | 
					
						
							| 
									
										
										
										
											2015-06-12 13:35:14 +02:00
										 |  |  | func (self *Vm) log(pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *stack, context *Context, err error) { | 
					
						
							| 
									
										
										
										
											2015-06-10 12:23:49 +02:00
										 |  |  | 	if Debug { | 
					
						
							|  |  |  | 		mem := make([]byte, len(memory.Data())) | 
					
						
							|  |  |  | 		copy(mem, memory.Data()) | 
					
						
							|  |  |  | 		stck := make([]*big.Int, len(stack.Data())) | 
					
						
							|  |  |  | 		copy(stck, stack.Data()) | 
					
						
							| 
									
										
										
										
											2015-06-10 12:57:37 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		object := context.self.(*state.StateObject) | 
					
						
							|  |  |  | 		storage := make(map[common.Hash][]byte) | 
					
						
							|  |  |  | 		object.EachStorage(func(k, v []byte) { | 
					
						
							|  |  |  | 			storage[common.BytesToHash(k)] = v | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-12 13:35:14 +02:00
										 |  |  | 		self.env.AddStructLog(StructLog{pc, op, new(big.Int).Set(gas), cost, mem, stck, storage, err}) | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-09-19 13:19:19 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-10-14 13:37:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-10 17:40:13 +02:00
										 |  |  | // Environment returns the current workable state of the VM | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | func (self *Vm) Env() Environment { | 
					
						
							|  |  |  | 	return self.env | 
					
						
							|  |  |  | } |