| 
									
										
										
										
											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
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type Address interface { | 
					
						
							|  |  |  | 	Call(in []byte) []byte | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-01-13 10:30:52 +01:00
										 |  |  | var Precompiled = PrecompiledContracts() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // XXX Could set directly. Testing requires resetting and setting of pre compiled contracts. | 
					
						
							|  |  |  | 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()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !crypto.ValidateSignatureValues(v, r, s) { | 
					
						
							|  |  |  | 		glog.V(logger.Error).Infof("EC RECOVER FAIL: 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 { | 
					
						
							| 
									
										
										
										
											2015-04-07 12:48:13 +02:00
										 |  |  | 		glog.V(logger.Error).Infof("EC RECOVER FAIL: ", 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 | 
					
						
							|  |  |  | 	return common.LeftPadBytes(crypto.Sha3(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 | 
					
						
							|  |  |  | } |