| 
									
										
										
										
											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
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // PrecompiledAccount represents a native ethereum contract | 
					
						
							| 
									
										
										
										
											2014-12-17 23:58:52 +01:00
										 |  |  | type PrecompiledAccount struct { | 
					
						
							| 
									
										
										
										
											2014-12-09 20:27:57 +01:00
										 |  |  | 	Gas func(l int) *big.Int | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | 	fn  func(in []byte) []byte | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // Call calls the native function | 
					
						
							| 
									
										
										
										
											2014-12-17 23:58:52 +01:00
										 |  |  | func (self PrecompiledAccount) Call(in []byte) []byte { | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | 	return self.fn(in) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // Precompiled contains the default set of ethereum contracts | 
					
						
							| 
									
										
										
										
											2015-01-13 10:30:52 +01:00
										 |  |  | var Precompiled = PrecompiledContracts() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | // PrecompiledContracts returns the default set of precompiled ethereum | 
					
						
							|  |  |  | // contracts defined by the ethereum yellow paper. | 
					
						
							| 
									
										
										
										
											2015-01-13 10:30:52 +01:00
										 |  |  | func PrecompiledContracts() map[string]*PrecompiledAccount { | 
					
						
							|  |  |  | 	return map[string]*PrecompiledAccount{ | 
					
						
							|  |  |  | 		// ECRECOVER | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 		string(common.LeftPadBytes([]byte{1}, 20)): &PrecompiledAccount{func(l int) *big.Int { | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 			return params.EcrecoverGas | 
					
						
							| 
									
										
										
										
											2015-01-13 10:30:52 +01:00
										 |  |  | 		}, ecrecoverFunc}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// SHA256 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 		string(common.LeftPadBytes([]byte{2}, 20)): &PrecompiledAccount{func(l int) *big.Int { | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 			n := big.NewInt(int64(l+31) / 32) | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 			n.Mul(n, params.Sha256WordGas) | 
					
						
							|  |  |  | 			return n.Add(n, params.Sha256Gas) | 
					
						
							| 
									
										
										
										
											2015-01-13 10:30:52 +01:00
										 |  |  | 		}, sha256Func}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// RIPEMD160 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 		string(common.LeftPadBytes([]byte{3}, 20)): &PrecompiledAccount{func(l int) *big.Int { | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 			n := big.NewInt(int64(l+31) / 32) | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 			n.Mul(n, params.Ripemd160WordGas) | 
					
						
							|  |  |  | 			return n.Add(n, params.Ripemd160Gas) | 
					
						
							| 
									
										
										
										
											2015-01-13 10:30:52 +01:00
										 |  |  | 		}, ripemd160Func}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 		string(common.LeftPadBytes([]byte{4}, 20)): &PrecompiledAccount{func(l int) *big.Int { | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 			n := big.NewInt(int64(l+31) / 32) | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 			n.Mul(n, params.IdentityWordGas) | 
					
						
							| 
									
										
										
										
											2015-01-13 10:30:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 			return n.Add(n, params.IdentityGas) | 
					
						
							| 
									
										
										
										
											2015-01-13 10:30:52 +01:00
										 |  |  | 		}, memCpy}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func sha256Func(in []byte) []byte { | 
					
						
							| 
									
										
										
										
											2014-10-31 12:37:43 +01:00
										 |  |  | 	return crypto.Sha256(in) | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func ripemd160Func(in []byte) []byte { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	return common.LeftPadBytes(crypto.Ripemd160(in), 32) | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-29 15:02:49 +02:00
										 |  |  | const ecRecoverInputLength = 128 | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-18 20:56:06 -07:00
										 |  |  | func ecrecoverFunc(in []byte) []byte { | 
					
						
							| 
									
										
										
										
											2015-06-09 16:03:05 +02:00
										 |  |  | 	in = common.RightPadBytes(in, 128) | 
					
						
							| 
									
										
										
										
											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]) | 
					
						
							| 
									
										
										
										
											2015-03-29 15:02:49 +02:00
										 |  |  | 	// Treat V as a 256bit integer | 
					
						
							| 
									
										
										
										
											2015-06-09 15:41:15 +02:00
										 |  |  | 	vbig := common.Bytes2Big(in[32:64]) | 
					
						
							|  |  |  | 	v := byte(vbig.Uint64()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	// tighter sig s values in homestead only apply to tx sigs | 
					
						
							|  |  |  | 	if !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 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-29 15:02:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-09 15:41:15 +02:00
										 |  |  | 	// v needs to be at the end and normalized for libsecp256k1 | 
					
						
							|  |  |  | 	vbignormal := new(big.Int).Sub(vbig, big.NewInt(27)) | 
					
						
							|  |  |  | 	vnormal := byte(vbignormal.Uint64()) | 
					
						
							|  |  |  | 	rsv := append(in[64:128], vnormal) | 
					
						
							| 
									
										
										
										
											2015-04-05 19:31:18 +02:00
										 |  |  | 	pubKey, err := crypto.Ecrecover(in[:32], rsv) | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							|  |  |  | func memCpy(in []byte) []byte { | 
					
						
							|  |  |  | 	return in | 
					
						
							|  |  |  | } |