| 
									
										
										
										
											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-10-18 13:31:20 +02:00
										 |  |  | package vm | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2015-03-13 13:44:15 +01:00
										 |  |  | 	"math" | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 	"math/big" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							| 
									
										
										
										
											2014-07-22 11:54:48 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // Type is the VM type accepted by **NewVm** | 
					
						
							| 
									
										
										
										
											2015-01-19 11:18:34 +01:00
										 |  |  | type Type byte | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 	StdVmTy Type = iota // Default standard VM | 
					
						
							|  |  |  | 	JitVmTy             // LLVM JIT VM | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 	MaxVmTy | 
					
						
							| 
									
										
										
										
											2015-03-16 21:46:47 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							| 
									
										
										
										
											2015-08-31 17:09:50 +02:00
										 |  |  | 	Pow256 = common.BigPow(2, 256) // Pow256 is 2**256 | 
					
						
							| 
									
										
										
										
											2015-03-16 21:46:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 	U256 = common.U256 // Shortcut to common.U256 | 
					
						
							|  |  |  | 	S256 = common.S256 // Shortcut to common.S256 | 
					
						
							| 
									
										
										
										
											2015-03-16 21:46:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 	Zero = common.Big0 // Shortcut to common.Big0 | 
					
						
							|  |  |  | 	One  = common.Big1 // Shortcut to common.Big1 | 
					
						
							| 
									
										
										
										
											2015-03-16 21:46:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-31 17:09:50 +02:00
										 |  |  | 	max = big.NewInt(math.MaxInt64) // Maximum 64 bit integer | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // calculates the memory size required for a step | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | func calcMemSize(off, l *big.Int) *big.Int { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	if l.Cmp(common.Big0) == 0 { | 
					
						
							|  |  |  | 		return common.Big0 | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return new(big.Int).Add(off, l) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // calculates the quadratic gas | 
					
						
							|  |  |  | func quadMemGas(mem *Memory, newMemSize, gas *big.Int) { | 
					
						
							|  |  |  | 	if newMemSize.Cmp(common.Big0) > 0 { | 
					
						
							|  |  |  | 		newMemSizeWords := toWordSize(newMemSize) | 
					
						
							|  |  |  | 		newMemSize.Mul(newMemSizeWords, u256(32)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 { | 
					
						
							|  |  |  | 			// be careful reusing variables here when changing. | 
					
						
							|  |  |  | 			// The order has been optimised to reduce allocation | 
					
						
							|  |  |  | 			oldSize := toWordSize(big.NewInt(int64(mem.Len()))) | 
					
						
							|  |  |  | 			pow := new(big.Int).Exp(oldSize, common.Big2, Zero) | 
					
						
							|  |  |  | 			linCoef := oldSize.Mul(oldSize, params.MemoryGas) | 
					
						
							|  |  |  | 			quadCoef := new(big.Int).Div(pow, params.QuadCoeffDiv) | 
					
						
							|  |  |  | 			oldTotalFee := new(big.Int).Add(linCoef, quadCoef) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			pow.Exp(newMemSizeWords, common.Big2, Zero) | 
					
						
							|  |  |  | 			linCoef = linCoef.Mul(newMemSizeWords, params.MemoryGas) | 
					
						
							|  |  |  | 			quadCoef = quadCoef.Div(pow, params.QuadCoeffDiv) | 
					
						
							|  |  |  | 			newTotalFee := linCoef.Add(linCoef, quadCoef) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			fee := newTotalFee.Sub(newTotalFee, oldTotalFee) | 
					
						
							|  |  |  | 			gas.Add(gas, fee) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | // Simple helper | 
					
						
							|  |  |  | func u256(n int64) *big.Int { | 
					
						
							|  |  |  | 	return big.NewInt(n) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Mainly used for print variables and passing to Print* | 
					
						
							|  |  |  | func toValue(val *big.Int) interface{} { | 
					
						
							|  |  |  | 	// Let's assume a string on right padded zero's | 
					
						
							|  |  |  | 	b := val.Bytes() | 
					
						
							|  |  |  | 	if b[0] != 0 && b[len(b)-1] == 0x0 && b[len(b)-2] == 0x0 { | 
					
						
							|  |  |  | 		return string(b) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return val | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-03-13 13:44:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // getData returns a slice from the data based on the start and size and pads | 
					
						
							|  |  |  | // up to size with zero's. This function is overflow safe. | 
					
						
							| 
									
										
										
										
											2015-03-19 22:45:03 +01:00
										 |  |  | func getData(data []byte, start, size *big.Int) []byte { | 
					
						
							|  |  |  | 	dlen := big.NewInt(int64(len(data))) | 
					
						
							| 
									
										
										
										
											2015-03-13 13:44:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-19 22:45:03 +01:00
										 |  |  | 	s := common.BigMin(start, dlen) | 
					
						
							|  |  |  | 	e := common.BigMin(new(big.Int).Add(s, size), dlen) | 
					
						
							|  |  |  | 	return common.RightPadBytes(data[s.Uint64():e.Uint64()], int(size.Uint64())) | 
					
						
							| 
									
										
										
										
											2015-03-13 13:44:15 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-03-28 20:03:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // useGas attempts to subtract the amount of gas and returns whether it was | 
					
						
							|  |  |  | // successful | 
					
						
							|  |  |  | func useGas(gas, amount *big.Int) bool { | 
					
						
							| 
									
										
										
										
											2015-03-28 20:03:25 +01:00
										 |  |  | 	if gas.Cmp(amount) < 0 { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Sub the amount of gas from the remaining | 
					
						
							|  |  |  | 	gas.Sub(gas, amount) | 
					
						
							|  |  |  | 	return true | 
					
						
							|  |  |  | } |