| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2014 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-23 18:35:11 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-04 10:28:02 +01:00
										 |  |  | package core | 
					
						
							| 
									
										
										
										
											2014-12-03 17:06:54 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"math/big" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-17 11:19:23 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2015-03-23 16:59:09 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/state" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/core/vm" | 
					
						
							| 
									
										
										
										
											2015-03-24 11:49:30 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							| 
									
										
										
										
											2014-12-03 17:06:54 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type Execution struct { | 
					
						
							| 
									
										
										
										
											2015-03-28 20:03:25 +01:00
										 |  |  | 	env     vm.Environment | 
					
						
							|  |  |  | 	address *common.Address | 
					
						
							|  |  |  | 	input   []byte | 
					
						
							|  |  |  | 	evm     vm.VirtualMachine | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-03 17:06:54 +01:00
										 |  |  | 	Gas, price, value *big.Int | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-17 11:19:23 +01:00
										 |  |  | func NewExecution(env vm.Environment, address *common.Address, input []byte, gas, gasPrice, value *big.Int) *Execution { | 
					
						
							| 
									
										
										
										
											2015-03-28 20:03:25 +01:00
										 |  |  | 	exe := &Execution{env: env, address: address, input: input, Gas: gas, price: gasPrice, value: value} | 
					
						
							|  |  |  | 	exe.evm = vm.NewVm(env) | 
					
						
							|  |  |  | 	return exe | 
					
						
							| 
									
										
										
										
											2014-12-03 17:06:54 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-17 11:19:23 +01:00
										 |  |  | func (self *Execution) Call(codeAddr common.Address, caller vm.ContextRef) ([]byte, error) { | 
					
						
							| 
									
										
										
										
											2014-12-03 17:06:54 +01:00
										 |  |  | 	// Retrieve the executing code | 
					
						
							| 
									
										
										
										
											2015-03-12 23:26:58 +01:00
										 |  |  | 	code := self.env.State().GetCode(codeAddr) | 
					
						
							| 
									
										
										
										
											2014-12-03 17:06:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-17 11:19:23 +01:00
										 |  |  | 	return self.exec(&codeAddr, code, caller) | 
					
						
							| 
									
										
										
										
											2014-12-03 17:06:54 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-28 20:03:25 +01:00
										 |  |  | func (self *Execution) Create(caller vm.ContextRef) (ret []byte, err error, account *state.StateObject) { | 
					
						
							| 
									
										
										
										
											2015-04-10 19:59:01 +02:00
										 |  |  | 	// Input must be nil for create | 
					
						
							|  |  |  | 	code := self.input | 
					
						
							|  |  |  | 	self.input = nil | 
					
						
							|  |  |  | 	ret, err = self.exec(nil, code, caller) | 
					
						
							| 
									
										
										
										
											2015-05-18 16:23:20 +02:00
										 |  |  | 	// Here we get an error if we run into maximum stack depth, | 
					
						
							|  |  |  | 	// See: https://github.com/ethereum/yellowpaper/pull/131 | 
					
						
							|  |  |  | 	// and YP definitions for CREATE instruction | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err, nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-28 20:03:25 +01:00
										 |  |  | 	account = self.env.State().GetStateObject(*self.address) | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-17 11:19:23 +01:00
										 |  |  | func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.ContextRef) (ret []byte, err error) { | 
					
						
							| 
									
										
										
										
											2014-12-19 00:23:00 +01:00
										 |  |  | 	env := self.env | 
					
						
							| 
									
										
										
										
											2015-03-28 20:03:25 +01:00
										 |  |  | 	evm := self.evm | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 	if env.Depth() > int(params.CallCreateDepth.Int64()) { | 
					
						
							| 
									
										
										
										
											2015-01-05 17:37:30 +01:00
										 |  |  | 		caller.ReturnGas(self.Gas, self.price) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-03 19:54:14 +02:00
										 |  |  | 		return nil, vm.DepthError | 
					
						
							| 
									
										
										
										
											2014-12-17 23:58:52 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-24 15:15:17 +01:00
										 |  |  | 	vsnapshot := env.State().Copy() | 
					
						
							| 
									
										
										
										
											2015-04-01 10:53:32 +02:00
										 |  |  | 	var createAccount bool | 
					
						
							| 
									
										
										
										
											2015-03-17 11:19:23 +01:00
										 |  |  | 	if self.address == nil { | 
					
						
							| 
									
										
										
										
											2015-01-13 20:31:31 +01:00
										 |  |  | 		// Generate a new address | 
					
						
							|  |  |  | 		nonce := env.State().GetNonce(caller.Address()) | 
					
						
							|  |  |  | 		env.State().SetNonce(caller.Address(), nonce+1) | 
					
						
							| 
									
										
										
										
											2015-04-01 10:53:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		addr := crypto.CreateAddress(caller.Address(), nonce) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-24 15:15:17 +01:00
										 |  |  | 		self.address = &addr | 
					
						
							| 
									
										
										
										
											2015-04-01 10:53:32 +02:00
										 |  |  | 		createAccount = true | 
					
						
							| 
									
										
										
										
											2015-01-13 20:31:31 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-24 15:15:17 +01:00
										 |  |  | 	snapshot := env.State().Copy() | 
					
						
							| 
									
										
										
										
											2015-01-13 20:31:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-01 10:53:32 +02:00
										 |  |  | 	var ( | 
					
						
							|  |  |  | 		from = env.State().GetStateObject(caller.Address()) | 
					
						
							|  |  |  | 		to   *state.StateObject | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	if createAccount { | 
					
						
							|  |  |  | 		to = env.State().CreateAccount(*self.address) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		to = env.State().GetOrNewStateObject(*self.address) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-12 14:40:40 +01:00
										 |  |  | 	err = env.Transfer(from, to, self.value) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2015-03-24 15:15:17 +01:00
										 |  |  | 		env.State().Set(vsnapshot) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		caller.ReturnGas(self.Gas, self.price) | 
					
						
							| 
									
										
										
										
											2015-01-12 14:40:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-05 19:51:25 +01:00
										 |  |  | 		return nil, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", self.value, from.Balance()) | 
					
						
							| 
									
										
										
										
											2014-12-09 20:27:57 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 13:44:15 +01:00
										 |  |  | 	context := vm.NewContext(caller, to, self.value, self.Gas, self.price) | 
					
						
							|  |  |  | 	context.SetCallCode(contextAddr, code) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-24 11:49:30 +01:00
										 |  |  | 	ret, err = evm.Run(context, self.input) | 
					
						
							| 
									
										
										
										
											2014-12-20 02:21:13 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		env.State().Set(snapshot) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-03 17:06:54 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } |