| 
									
										
										
										
											2014-10-18 13:31:20 +02:00
										 |  |  | package vm | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2014-07-26 11:24:44 +02:00
										 |  |  | 	"math/big" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-23 15:01:27 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/ethcrypto" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/ethutil" | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | // BIG FAT WARNING. THIS VM IS NOT YET IS USE! | 
					
						
							|  |  |  | // I want to get all VM tests pass first before updating this VM | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | type Vm struct { | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 	env   Environment | 
					
						
							|  |  |  | 	err   error | 
					
						
							| 
									
										
										
										
											2014-10-11 00:41:37 +02:00
										 |  |  | 	depth int | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | func New(env Environment, typ Type) VirtualMachine { | 
					
						
							|  |  |  | 	switch typ { | 
					
						
							|  |  |  | 	case DebugVmTy: | 
					
						
							|  |  |  | 		return NewDebugVm(env) | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return &Vm{env: env} | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | func (self *Vm) RunClosure(closure *Closure) (ret []byte, err error) { | 
					
						
							| 
									
										
										
										
											2014-10-11 00:41:37 +02:00
										 |  |  | 	self.depth++ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 	// Recover from any require exception | 
					
						
							|  |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  | 			ret = closure.Return(nil) | 
					
						
							|  |  |  | 			err = fmt.Errorf("%v", r) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Don't bother with the execution if there's no code. | 
					
						
							|  |  |  | 	if len(closure.Code) == 0 { | 
					
						
							|  |  |  | 		return closure.Return(nil), nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		op OpCode | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 		mem     = &Memory{} | 
					
						
							|  |  |  | 		stack   = NewStack() | 
					
						
							|  |  |  | 		pc      = 0 | 
					
						
							|  |  |  | 		step    = 0 | 
					
						
							|  |  |  | 		require = func(m int) { | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			if stack.Len() < m { | 
					
						
							|  |  |  | 				panic(fmt.Sprintf("%04v (%v) stack err size = %d, required = %d", pc, op, stack.Len(), m)) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		// The base for all big integer arithmetic | 
					
						
							|  |  |  | 		base := new(big.Int) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		step++ | 
					
						
							|  |  |  | 		// Get the memory location of pc | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 		op := closure.GetOp(pc) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		gas := new(big.Int) | 
					
						
							|  |  |  | 		addStepGasUsage := func(amount *big.Int) { | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 			gas.Add(gas, amount) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		addStepGasUsage(GasStep) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | 		var newMemSize *big.Int = ethutil.Big0 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		switch op { | 
					
						
							|  |  |  | 		case STOP: | 
					
						
							|  |  |  | 			gas.Set(ethutil.Big0) | 
					
						
							|  |  |  | 		case SUICIDE: | 
					
						
							|  |  |  | 			gas.Set(ethutil.Big0) | 
					
						
							|  |  |  | 		case SLOAD: | 
					
						
							|  |  |  | 			gas.Set(GasSLoad) | 
					
						
							|  |  |  | 		case SSTORE: | 
					
						
							|  |  |  | 			var mult *big.Int | 
					
						
							|  |  |  | 			y, x := stack.Peekn() | 
					
						
							|  |  |  | 			val := closure.GetStorage(x) | 
					
						
							|  |  |  | 			if val.BigInt().Cmp(ethutil.Big0) == 0 && len(y.Bytes()) > 0 { | 
					
						
							|  |  |  | 				mult = ethutil.Big2 | 
					
						
							|  |  |  | 			} else if val.BigInt().Cmp(ethutil.Big0) != 0 && len(y.Bytes()) == 0 { | 
					
						
							|  |  |  | 				mult = ethutil.Big0 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				mult = ethutil.Big1 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			gas = new(big.Int).Mul(mult, GasSStore) | 
					
						
							|  |  |  | 		case BALANCE: | 
					
						
							|  |  |  | 			gas.Set(GasBalance) | 
					
						
							|  |  |  | 		case MSTORE: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | 			newMemSize = calcMemSize(stack.Peek(), u256(32)) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case MLOAD: | 
					
						
							|  |  |  | 			require(1) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | 			newMemSize = calcMemSize(stack.Peek(), u256(32)) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case MSTORE8: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | 			newMemSize = calcMemSize(stack.Peek(), u256(1)) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case RETURN: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | 			newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2]) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case SHA3: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			gas.Set(GasSha) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | 			newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2]) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case CALLDATACOPY: | 
					
						
							| 
									
										
										
										
											2014-09-16 11:35:26 +02:00
										 |  |  | 			require(2) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | 			newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3]) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case CODECOPY: | 
					
						
							|  |  |  | 			require(3) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | 			newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3]) | 
					
						
							| 
									
										
										
										
											2014-09-08 00:49:25 +02:00
										 |  |  | 		case EXTCODECOPY: | 
					
						
							|  |  |  | 			require(4) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-16 11:35:26 +02:00
										 |  |  | 			newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-4]) | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | 		case CALL, CALLCODE: | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			require(7) | 
					
						
							|  |  |  | 			gas.Set(GasCall) | 
					
						
							|  |  |  | 			addStepGasUsage(stack.data[stack.Len()-1]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02: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]) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | 			newMemSize = ethutil.BigMax(x, y) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case CREATE: | 
					
						
							|  |  |  | 			require(3) | 
					
						
							|  |  |  | 			gas.Set(GasCreate) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | 			newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-3]) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | 		if newMemSize.Cmp(ethutil.Big0) > 0 { | 
					
						
							| 
									
										
										
										
											2014-09-15 22:11:05 +02:00
										 |  |  | 			newMemSize.Add(newMemSize, u256(31)) | 
					
						
							|  |  |  | 			newMemSize.Div(newMemSize, u256(32)) | 
					
						
							|  |  |  | 			newMemSize.Mul(newMemSize, u256(32)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | 			if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 { | 
					
						
							| 
									
										
										
										
											2014-09-15 22:11:05 +02:00
										 |  |  | 				memGasUsage := new(big.Int).Sub(newMemSize, u256(int64(mem.Len()))) | 
					
						
							|  |  |  | 				memGasUsage.Mul(GasMemory, memGasUsage) | 
					
						
							|  |  |  | 				memGasUsage.Div(memGasUsage, u256(32)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | 				addStepGasUsage(memGasUsage) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if !closure.UseGas(gas) { | 
					
						
							|  |  |  | 			err := fmt.Errorf("Insufficient gas for %v. req %v has %v", op, gas, closure.Gas) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			closure.UseGas(closure.Gas) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return closure.Return(nil), err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 01:11:01 +02:00
										 |  |  | 		mem.Resize(newMemSize.Uint64()) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		switch op { | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 		// 0x20 range | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case ADD: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			x, y := stack.Popn() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			base.Add(y, x) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			U256(base) | 
					
						
							| 
									
										
										
										
											2014-08-08 12:04:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			// Pop result back on the stack | 
					
						
							|  |  |  | 			stack.Push(base) | 
					
						
							|  |  |  | 		case SUB: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			x, y := stack.Popn() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			base.Sub(y, x) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			U256(base) | 
					
						
							| 
									
										
										
										
											2014-08-08 12:04:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			// Pop result back on the stack | 
					
						
							|  |  |  | 			stack.Push(base) | 
					
						
							|  |  |  | 		case MUL: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			x, y := stack.Popn() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			base.Mul(y, x) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			U256(base) | 
					
						
							| 
									
										
										
										
											2014-08-08 12:04:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			// Pop result back on the stack | 
					
						
							|  |  |  | 			stack.Push(base) | 
					
						
							|  |  |  | 		case DIV: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			x, y := stack.Popn() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-23 12:36:47 +02:00
										 |  |  | 			if x.Cmp(ethutil.Big0) != 0 { | 
					
						
							|  |  |  | 				base.Div(y, x) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			U256(base) | 
					
						
							| 
									
										
										
										
											2014-08-08 12:04:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			// Pop result back on the stack | 
					
						
							|  |  |  | 			stack.Push(base) | 
					
						
							|  |  |  | 		case SDIV: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			y, x := S256(stack.Pop()), S256(stack.Pop()) | 
					
						
							| 
									
										
										
										
											2014-07-25 09:57:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			if x.Cmp(ethutil.Big0) == 0 { | 
					
						
							|  |  |  | 				base.Set(ethutil.Big0) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				n := new(big.Int) | 
					
						
							|  |  |  | 				if new(big.Int).Mul(y, x).Cmp(ethutil.Big0) < 0 { | 
					
						
							|  |  |  | 					n.SetInt64(-1) | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					n.SetInt64(1) | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-07-25 09:57:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 				base.Div(y.Abs(y), x.Mul(x.Abs(x), n)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				U256(base) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-08-08 12:04:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-25 09:57:47 +02:00
										 |  |  | 			stack.Push(base) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case MOD: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			x, y := stack.Popn() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			base.Mod(y, x) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			U256(base) | 
					
						
							| 
									
										
										
										
											2014-08-08 12:04:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			stack.Push(base) | 
					
						
							|  |  |  | 		case SMOD: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			y, x := S256(stack.Pop()), S256(stack.Pop()) | 
					
						
							| 
									
										
										
										
											2014-07-25 09:57:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			if x.Cmp(ethutil.Big0) == 0 { | 
					
						
							|  |  |  | 				base.Set(ethutil.Big0) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				n := new(big.Int) | 
					
						
							|  |  |  | 				if y.Cmp(ethutil.Big0) < 0 { | 
					
						
							|  |  |  | 					n.SetInt64(-1) | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					n.SetInt64(1) | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-07-25 09:57:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 				base.Mod(y.Abs(y), x.Mul(x.Abs(x), n)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				U256(base) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-08-08 12:04:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-25 09:57:47 +02:00
										 |  |  | 			stack.Push(base) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case EXP: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			x, y := stack.Popn() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			base.Exp(y, x, Pow256) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			U256(base) | 
					
						
							| 
									
										
										
										
											2014-08-08 12:04:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			stack.Push(base) | 
					
						
							| 
									
										
										
										
											2014-10-27 11:44:16 +01:00
										 |  |  | 		case BNOT: | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			require(1) | 
					
						
							|  |  |  | 			base.Sub(Pow256, stack.Pop()) | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			base = U256(base) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			stack.Push(base) | 
					
						
							|  |  |  | 		case LT: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			x, y := stack.Popn() | 
					
						
							|  |  |  | 			// x < y | 
					
						
							|  |  |  | 			if y.Cmp(x) < 0 { | 
					
						
							|  |  |  | 				stack.Push(ethutil.BigTrue) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				stack.Push(ethutil.BigFalse) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case GT: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			x, y := stack.Popn() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// x > y | 
					
						
							|  |  |  | 			if y.Cmp(x) > 0 { | 
					
						
							|  |  |  | 				stack.Push(ethutil.BigTrue) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				stack.Push(ethutil.BigFalse) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case SLT: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			y, x := S256(stack.Pop()), S256(stack.Pop()) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			// x < y | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			if y.Cmp(S256(x)) < 0 { | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 				stack.Push(ethutil.BigTrue) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				stack.Push(ethutil.BigFalse) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case SGT: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			y, x := S256(stack.Pop()), S256(stack.Pop()) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// x > y | 
					
						
							|  |  |  | 			if y.Cmp(x) > 0 { | 
					
						
							|  |  |  | 				stack.Push(ethutil.BigTrue) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				stack.Push(ethutil.BigFalse) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case EQ: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			x, y := stack.Popn() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// x == y | 
					
						
							|  |  |  | 			if x.Cmp(y) == 0 { | 
					
						
							|  |  |  | 				stack.Push(ethutil.BigTrue) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				stack.Push(ethutil.BigFalse) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case NOT: | 
					
						
							|  |  |  | 			require(1) | 
					
						
							|  |  |  | 			x := stack.Pop() | 
					
						
							|  |  |  | 			if x.Cmp(ethutil.BigFalse) > 0 { | 
					
						
							|  |  |  | 				stack.Push(ethutil.BigFalse) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				stack.Push(ethutil.BigTrue) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// 0x10 range | 
					
						
							|  |  |  | 		case AND: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			x, y := stack.Popn() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(base.And(y, x)) | 
					
						
							|  |  |  | 		case OR: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			x, y := stack.Popn() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(base.Or(y, x)) | 
					
						
							|  |  |  | 		case XOR: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			x, y := stack.Popn() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(base.Xor(y, x)) | 
					
						
							|  |  |  | 		case BYTE: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			val, th := stack.Popn() | 
					
						
							|  |  |  | 			if th.Cmp(big.NewInt(32)) < 0 && th.Cmp(big.NewInt(int64(len(val.Bytes())))) < 0 { | 
					
						
							| 
									
										
										
										
											2014-07-22 15:57:54 +02:00
										 |  |  | 				byt := big.NewInt(int64(ethutil.LeftPadBytes(val.Bytes(), 32)[th.Int64()])) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 				stack.Push(byt) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				stack.Push(ethutil.BigFalse) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-08-21 19:23:54 +02:00
										 |  |  | 		case ADDMOD: | 
					
						
							|  |  |  | 			require(3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			x := stack.Pop() | 
					
						
							|  |  |  | 			y := stack.Pop() | 
					
						
							|  |  |  | 			z := stack.Pop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			base.Add(x, y) | 
					
						
							|  |  |  | 			base.Mod(base, z) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			U256(base) | 
					
						
							| 
									
										
										
										
											2014-08-21 19:23:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(base) | 
					
						
							|  |  |  | 		case MULMOD: | 
					
						
							|  |  |  | 			require(3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			x := stack.Pop() | 
					
						
							|  |  |  | 			y := stack.Pop() | 
					
						
							|  |  |  | 			z := stack.Pop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			base.Mul(x, y) | 
					
						
							|  |  |  | 			base.Mod(base, z) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-15 17:12:26 +02:00
										 |  |  | 			U256(base) | 
					
						
							| 
									
										
										
										
											2014-08-21 19:23:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(base) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// 0x20 range | 
					
						
							|  |  |  | 		case SHA3: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			size, offset := stack.Popn() | 
					
						
							| 
									
										
										
										
											2014-10-08 12:06:39 +02:00
										 |  |  | 			data := ethcrypto.Sha3(mem.Get(offset.Int64(), size.Int64())) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(ethutil.BigD(data)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// 0x30 range | 
					
						
							|  |  |  | 		case ADDRESS: | 
					
						
							|  |  |  | 			stack.Push(ethutil.BigD(closure.Address())) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case BALANCE: | 
					
						
							|  |  |  | 			require(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			addr := stack.Pop().Bytes() | 
					
						
							|  |  |  | 			balance := self.env.State().GetBalance(addr) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(balance) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case ORIGIN: | 
					
						
							|  |  |  | 			origin := self.env.Origin() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(ethutil.BigD(origin)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case CALLER: | 
					
						
							|  |  |  | 			caller := closure.caller.Address() | 
					
						
							|  |  |  | 			stack.Push(ethutil.BigD(caller)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case CALLVALUE: | 
					
						
							| 
									
										
										
										
											2014-10-15 00:40:41 +02:00
										 |  |  | 			value := closure.exe.value | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case CALLDATALOAD: | 
					
						
							|  |  |  | 			require(1) | 
					
						
							|  |  |  | 			var ( | 
					
						
							|  |  |  | 				offset  = stack.Pop() | 
					
						
							|  |  |  | 				data    = make([]byte, 32) | 
					
						
							|  |  |  | 				lenData = big.NewInt(int64(len(closure.Args))) | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if lenData.Cmp(offset) >= 0 { | 
					
						
							|  |  |  | 				length := new(big.Int).Add(offset, ethutil.Big32) | 
					
						
							|  |  |  | 				length = ethutil.BigMin(length, lenData) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				copy(data, closure.Args[offset.Int64():length.Int64()]) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(ethutil.BigD(data)) | 
					
						
							|  |  |  | 		case CALLDATASIZE: | 
					
						
							|  |  |  | 			l := int64(len(closure.Args)) | 
					
						
							|  |  |  | 			stack.Push(big.NewInt(l)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case CALLDATACOPY: | 
					
						
							|  |  |  | 			var ( | 
					
						
							|  |  |  | 				size = int64(len(closure.Args)) | 
					
						
							|  |  |  | 				mOff = stack.Pop().Int64() | 
					
						
							|  |  |  | 				cOff = stack.Pop().Int64() | 
					
						
							|  |  |  | 				l    = stack.Pop().Int64() | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if cOff > size { | 
					
						
							|  |  |  | 				cOff = 0 | 
					
						
							|  |  |  | 				l = 0 | 
					
						
							|  |  |  | 			} else if cOff+l > size { | 
					
						
							|  |  |  | 				l = 0 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			code := closure.Args[cOff : cOff+l] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			mem.Set(mOff, l, code) | 
					
						
							| 
									
										
										
										
											2014-09-08 00:49:25 +02:00
										 |  |  | 		case CODESIZE, EXTCODESIZE: | 
					
						
							|  |  |  | 			var code []byte | 
					
						
							|  |  |  | 			if op == EXTCODECOPY { | 
					
						
							|  |  |  | 				addr := stack.Pop().Bytes() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				code = self.env.State().GetCode(addr) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				code = closure.Code | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			l := big.NewInt(int64(len(code))) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			stack.Push(l) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-08 00:49:25 +02:00
										 |  |  | 		case CODECOPY, EXTCODECOPY: | 
					
						
							|  |  |  | 			var code []byte | 
					
						
							|  |  |  | 			if op == EXTCODECOPY { | 
					
						
							|  |  |  | 				addr := stack.Pop().Bytes() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				code = self.env.State().GetCode(addr) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				code = closure.Code | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			var ( | 
					
						
							| 
									
										
										
										
											2014-09-08 00:49:25 +02:00
										 |  |  | 				size = int64(len(code)) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 				mOff = stack.Pop().Int64() | 
					
						
							|  |  |  | 				cOff = stack.Pop().Int64() | 
					
						
							|  |  |  | 				l    = stack.Pop().Int64() | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if cOff > size { | 
					
						
							|  |  |  | 				cOff = 0 | 
					
						
							|  |  |  | 				l = 0 | 
					
						
							|  |  |  | 			} else if cOff+l > size { | 
					
						
							|  |  |  | 				l = 0 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-08 00:49:25 +02:00
										 |  |  | 			codeCopy := code[cOff : cOff+l] | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-08 00:49:25 +02:00
										 |  |  | 			mem.Set(mOff, l, codeCopy) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case GASPRICE: | 
					
						
							|  |  |  | 			stack.Push(closure.Price) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// 0x40 range | 
					
						
							|  |  |  | 		case PREVHASH: | 
					
						
							|  |  |  | 			prevHash := self.env.PrevHash() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(ethutil.BigD(prevHash)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case COINBASE: | 
					
						
							|  |  |  | 			coinbase := self.env.Coinbase() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(ethutil.BigD(coinbase)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case TIMESTAMP: | 
					
						
							|  |  |  | 			time := self.env.Time() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(big.NewInt(time)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case NUMBER: | 
					
						
							|  |  |  | 			number := self.env.BlockNumber() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(number) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case DIFFICULTY: | 
					
						
							|  |  |  | 			difficulty := self.env.Difficulty() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(difficulty) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case GASLIMIT: | 
					
						
							|  |  |  | 			// TODO | 
					
						
							|  |  |  | 			stack.Push(big.NewInt(0)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// 0x50 range | 
					
						
							|  |  |  | 		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: | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 			a := int(op - PUSH1 + 1) | 
					
						
							|  |  |  | 			val := ethutil.BigD(closure.GetBytes(int(pc+1), a)) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			// Push value to stack | 
					
						
							|  |  |  | 			stack.Push(val) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 			pc += a | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 			step += int(op) - int(PUSH1) + 1 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case POP: | 
					
						
							|  |  |  | 			require(1) | 
					
						
							|  |  |  | 			stack.Pop() | 
					
						
							| 
									
										
										
										
											2014-08-21 18:15:09 +02:00
										 |  |  | 		case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16: | 
					
						
							| 
									
										
										
										
											2014-09-15 22:11:05 +02:00
										 |  |  | 			n := int(op - DUP1 + 1) | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 			stack.Dupn(n) | 
					
						
							| 
									
										
										
										
											2014-08-21 18:15:09 +02:00
										 |  |  | 		case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16: | 
					
						
							| 
									
										
										
										
											2014-09-15 22:11:05 +02:00
										 |  |  | 			n := int(op - SWAP1 + 2) | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 			stack.Swapn(n) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case MLOAD: | 
					
						
							|  |  |  | 			require(1) | 
					
						
							|  |  |  | 			offset := stack.Pop() | 
					
						
							|  |  |  | 			val := ethutil.BigD(mem.Get(offset.Int64(), 32)) | 
					
						
							|  |  |  | 			stack.Push(val) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case MSTORE: // Store the value at stack top-1 in to memory at location stack top | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			// Pop value of the stack | 
					
						
							|  |  |  | 			val, mStart := stack.Popn() | 
					
						
							|  |  |  | 			mem.Set(mStart.Int64(), 32, ethutil.BigToBytes(val, 256)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case MSTORE8: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							| 
									
										
										
										
											2014-09-15 22:11:05 +02:00
										 |  |  | 			off := stack.Pop() | 
					
						
							|  |  |  | 			val := stack.Pop() | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-15 22:11:05 +02:00
										 |  |  | 			mem.store[off.Int64()] = byte(val.Int64() & 0xff) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case SLOAD: | 
					
						
							|  |  |  | 			require(1) | 
					
						
							|  |  |  | 			loc := stack.Pop() | 
					
						
							|  |  |  | 			val := closure.GetStorage(loc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			stack.Push(val.BigInt()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case SSTORE: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			val, loc := stack.Popn() | 
					
						
							|  |  |  | 			closure.SetStorage(loc, ethutil.NewValue(val)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-15 16:19:10 +02:00
										 |  |  | 			closure.message.AddStorageChange(loc.Bytes()) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case JUMP: | 
					
						
							|  |  |  | 			require(1) | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 			pc = int(stack.Pop().Int64()) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			// Reduce pc by one because of the increment that's at the end of this for loop | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		case JUMPI: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			cond, pos := stack.Popn() | 
					
						
							|  |  |  | 			if cond.Cmp(ethutil.BigTrue) >= 0 { | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 				pc = int(pos.Int64()) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 				if closure.GetOp(int(pc)) != JUMPDEST { | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | 					return closure.Return(nil), fmt.Errorf("JUMP missed JUMPDEST %v", pc) | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | 		case JUMPDEST: | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case PC: | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 			stack.Push(u256(int64(pc))) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case MSIZE: | 
					
						
							|  |  |  | 			stack.Push(big.NewInt(int64(mem.Len()))) | 
					
						
							|  |  |  | 		case GAS: | 
					
						
							|  |  |  | 			stack.Push(closure.Gas) | 
					
						
							|  |  |  | 			// 0x60 range | 
					
						
							|  |  |  | 		case CREATE: | 
					
						
							|  |  |  | 			require(3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var ( | 
					
						
							|  |  |  | 				err          error | 
					
						
							|  |  |  | 				value        = stack.Pop() | 
					
						
							|  |  |  | 				size, offset = stack.Popn() | 
					
						
							| 
									
										
										
										
											2014-08-25 11:29:42 +02:00
										 |  |  | 				input        = mem.Get(offset.Int64(), size.Int64()) | 
					
						
							|  |  |  | 				gas          = new(big.Int).Set(closure.Gas) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// Snapshot the current stack so we are able to | 
					
						
							|  |  |  | 				// revert back to it later. | 
					
						
							| 
									
										
										
										
											2014-10-08 16:11:36 +02:00
										 |  |  | 				//snapshot = self.env.State().Copy() | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Generate a new address | 
					
						
							|  |  |  | 			addr := ethcrypto.CreateAddress(closure.Address(), closure.object.Nonce) | 
					
						
							|  |  |  | 			closure.object.Nonce++ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-25 11:29:42 +02:00
										 |  |  | 			closure.UseGas(closure.Gas) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | 			msg := NewExecution(self, addr, input, gas, closure.Price, value) | 
					
						
							| 
									
										
										
										
											2014-09-10 00:19:20 +02:00
										 |  |  | 			ret, err := msg.Exec(addr, closure) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				stack.Push(ethutil.BigFalse) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// Revert the state as it was before. | 
					
						
							| 
									
										
										
										
											2014-10-08 16:11:36 +02:00
										 |  |  | 				//self.env.State().Set(snapshot) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2014-08-25 11:29:42 +02:00
										 |  |  | 				msg.object.Code = ret | 
					
						
							| 
									
										
										
										
											2014-08-11 16:23:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-25 11:29:42 +02:00
										 |  |  | 				stack.Push(ethutil.BigD(addr)) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-08-25 11:29:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | 		case CALL, CALLCODE: | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			require(7) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			gas := stack.Pop() | 
					
						
							|  |  |  | 			// Pop gas and value of the stack. | 
					
						
							|  |  |  | 			value, addr := stack.Popn() | 
					
						
							|  |  |  | 			// Pop input size and offset | 
					
						
							|  |  |  | 			inSize, inOffset := stack.Popn() | 
					
						
							|  |  |  | 			// Pop return size and offset | 
					
						
							|  |  |  | 			retSize, retOffset := stack.Popn() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Get the arguments from the memory | 
					
						
							|  |  |  | 			args := mem.Get(inOffset.Int64(), inSize.Int64()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-10 00:19:20 +02:00
										 |  |  | 			var executeAddr []byte | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | 			if op == CALLCODE { | 
					
						
							| 
									
										
										
										
											2014-09-10 00:19:20 +02:00
										 |  |  | 				executeAddr = closure.Address() | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				executeAddr = addr.Bytes() | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | 			msg := NewExecution(self, executeAddr, args, gas, closure.Price, value) | 
					
						
							| 
									
										
										
										
											2014-09-10 00:19:20 +02:00
										 |  |  | 			ret, err := msg.Exec(addr.Bytes(), closure) | 
					
						
							| 
									
										
										
										
											2014-08-25 11:29:42 +02:00
										 |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 				stack.Push(ethutil.BigFalse) | 
					
						
							|  |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2014-08-25 11:29:42 +02:00
										 |  |  | 				stack.Push(ethutil.BigTrue) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				mem.Set(retOffset.Int64(), retSize.Int64(), ret) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 		case RETURN: | 
					
						
							|  |  |  | 			require(2) | 
					
						
							|  |  |  | 			size, offset := stack.Popn() | 
					
						
							|  |  |  | 			ret := mem.Get(offset.Int64(), size.Int64()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return closure.Return(ret), nil | 
					
						
							|  |  |  | 		case SUICIDE: | 
					
						
							|  |  |  | 			require(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			receiver := self.env.State().GetOrNewStateObject(stack.Pop().Bytes()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-22 15:22:21 +02:00
										 |  |  | 			receiver.AddAmount(closure.object.Balance()) | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			closure.object.MarkForDeletion() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			fallthrough | 
					
						
							|  |  |  | 		case STOP: // Stop the closure | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return closure.Return(nil), nil | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			vmlogger.Debugf("(pc) %-3v Invalid opcode %x\n", pc, op) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-18 01:02:15 +02:00
										 |  |  | 			//panic(fmt.Sprintf("Invalid opcode %x", op)) | 
					
						
							| 
									
										
										
										
											2014-09-16 11:35:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 			return closure.Return(nil), fmt.Errorf("Invalid opcode %x", op) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 		pc++ | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | func (self *Vm) Env() Environment { | 
					
						
							|  |  |  | 	return self.env | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | func (self *Vm) Depth() int { | 
					
						
							|  |  |  | 	return self.depth | 
					
						
							| 
									
										
										
										
											2014-09-19 13:19:19 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-10-14 13:37:26 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (self *Vm) Printf(format string, v ...interface{}) VirtualMachine { return self } | 
					
						
							|  |  |  | func (self *Vm) Endl() VirtualMachine                                  { return self } |