| 
									
										
										
										
											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-10-08 12:01:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"math/big" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2015-03-18 20:56:06 -07:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2015-04-07 12:48:13 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger" | 
					
						
							| 
									
										
										
										
											2015-04-05 19:31:18 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger/glog" | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | // Precompiled contract is the basic interface for native Go contracts. The implementation | 
					
						
							|  |  |  | // requires a deterministic gas count based on the input size of the Run method of the | 
					
						
							|  |  |  | // contract. | 
					
						
							|  |  |  | type PrecompiledContract interface { | 
					
						
							|  |  |  | 	RequiredGas(inputSize int) *big.Int // RequiredPrice calculates the contract gas use | 
					
						
							|  |  |  | 	Run(input []byte) []byte            // Run runs the precompiled contract | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | // Precompiled contains the default set of ethereum contracts | 
					
						
							|  |  |  | var PrecompiledContracts = map[common.Address]PrecompiledContract{ | 
					
						
							|  |  |  | 	common.BytesToAddress([]byte{1}): &ecrecover{}, | 
					
						
							|  |  |  | 	common.BytesToAddress([]byte{2}): &sha256{}, | 
					
						
							|  |  |  | 	common.BytesToAddress([]byte{3}): &ripemd160{}, | 
					
						
							|  |  |  | 	common.BytesToAddress([]byte{4}): &dataCopy{}, | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | // RunPrecompile runs and evaluate the output of a precompiled contract defined in contracts.go | 
					
						
							|  |  |  | func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) { | 
					
						
							|  |  |  | 	gas := p.RequiredGas(len(input)) | 
					
						
							|  |  |  | 	if contract.UseGas(gas) { | 
					
						
							|  |  |  | 		ret = p.Run(input) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return ret, nil | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return nil, ErrOutOfGas | 
					
						
							| 
									
										
										
										
											2015-01-13 10:30:52 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | // ECRECOVER implemented as a native contract | 
					
						
							|  |  |  | type ecrecover struct{} | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | func (c *ecrecover) RequiredGas(inputSize int) *big.Int { | 
					
						
							|  |  |  | 	return params.EcrecoverGas | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | func (c *ecrecover) Run(in []byte) []byte { | 
					
						
							|  |  |  | 	const ecRecoverInputLength = 128 | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	in = common.RightPadBytes(in, ecRecoverInputLength) | 
					
						
							| 
									
										
										
										
											2015-06-09 15:41:15 +02:00
										 |  |  | 	// "in" is (hash, v, r, s), each 32 bytes | 
					
						
							|  |  |  | 	// but for ecrecover we want (r, s, v) | 
					
						
							| 
									
										
										
										
											2015-03-29 15:02:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-09 15:41:15 +02:00
										 |  |  | 	r := common.BytesToBig(in[64:96]) | 
					
						
							|  |  |  | 	s := common.BytesToBig(in[96:128]) | 
					
						
							| 
									
										
										
										
											2017-01-05 12:35:23 +02:00
										 |  |  | 	v := in[63] - 27 | 
					
						
							| 
									
										
										
										
											2015-06-09 15:41:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	// tighter sig s values in homestead only apply to tx sigs | 
					
						
							| 
									
										
										
										
											2017-01-05 12:35:23 +02:00
										 |  |  | 	if common.Bytes2Big(in[32:63]).BitLen() > 0 || !crypto.ValidateSignatureValues(v, r, s, false) { | 
					
						
							| 
									
										
										
										
											2016-08-05 23:12:52 +02:00
										 |  |  | 		glog.V(logger.Detail).Infof("ECRECOVER error: v, r or s value invalid") | 
					
						
							| 
									
										
										
										
											2015-03-18 20:56:06 -07:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-05 12:35:23 +02:00
										 |  |  | 	// v needs to be at the end for libsecp256k1 | 
					
						
							|  |  |  | 	pubKey, err := crypto.Ecrecover(in[:32], append(in[64:128], v)) | 
					
						
							| 
									
										
										
										
											2015-03-29 15:02:49 +02:00
										 |  |  | 	// make sure the public key is a valid one | 
					
						
							| 
									
										
										
										
											2015-04-05 19:31:18 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2016-08-05 23:12:52 +02:00
										 |  |  | 		glog.V(logger.Detail).Infoln("ECRECOVER error: ", err) | 
					
						
							| 
									
										
										
										
											2015-03-18 20:56:06 -07:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-29 15:02:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-18 20:56:06 -07:00
										 |  |  | 	// the first byte of pubkey is bitcoin heritage | 
					
						
							| 
									
										
										
										
											2016-02-21 18:40:27 +00:00
										 |  |  | 	return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32) | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-01-05 17:37:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | // SHA256 implemented as a native contract | 
					
						
							|  |  |  | type sha256 struct{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *sha256) RequiredGas(inputSize int) *big.Int { | 
					
						
							|  |  |  | 	n := big.NewInt(int64(inputSize+31) / 32) | 
					
						
							|  |  |  | 	n.Mul(n, params.Sha256WordGas) | 
					
						
							|  |  |  | 	return n.Add(n, params.Sha256Gas) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | func (c *sha256) Run(in []byte) []byte { | 
					
						
							|  |  |  | 	return crypto.Sha256(in) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RIPMED160 implemented as a native contract | 
					
						
							|  |  |  | type ripemd160 struct{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *ripemd160) RequiredGas(inputSize int) *big.Int { | 
					
						
							|  |  |  | 	n := big.NewInt(int64(inputSize+31) / 32) | 
					
						
							|  |  |  | 	n.Mul(n, params.Ripemd160WordGas) | 
					
						
							|  |  |  | 	return n.Add(n, params.Ripemd160Gas) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | func (c *ripemd160) Run(in []byte) []byte { | 
					
						
							|  |  |  | 	return common.LeftPadBytes(crypto.Ripemd160(in), 32) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // data copy implemented as a native contract | 
					
						
							|  |  |  | type dataCopy struct{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *dataCopy) RequiredGas(inputSize int) *big.Int { | 
					
						
							|  |  |  | 	n := big.NewInt(int64(inputSize+31) / 32) | 
					
						
							|  |  |  | 	n.Mul(n, params.IdentityWordGas) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return n.Add(n, params.IdentityGas) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | func (c *dataCopy) Run(in []byte) []byte { | 
					
						
							| 
									
										
										
										
											2015-01-05 17:37:30 +01:00
										 |  |  | 	return in | 
					
						
							|  |  |  | } |