| 
									
										
										
										
											2014-10-18 13:31:20 +02:00
										 |  |  | package vm | 
					
						
							| 
									
										
										
										
											2014-10-08 12:01:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"math/big" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-31 12:37:43 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											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-01-13 10:30:52 +01:00
										 |  |  | 			return GasEcrecover | 
					
						
							|  |  |  | 		}, 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) | 
					
						
							|  |  |  | 			n.Mul(n, GasSha256Word) | 
					
						
							|  |  |  | 			return n.Add(n, GasSha256Base) | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  | 			n.Mul(n, GasRipemdWord) | 
					
						
							|  |  |  | 			return n.Add(n, GasRipemdBase) | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  | 			n.Mul(n, GasIdentityWord) | 
					
						
							| 
									
										
										
										
											2015-01-13 10:30:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-02 16:32:02 +01:00
										 |  |  | 			return n.Add(n, GasIdentityBase) | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func ecrecoverFunc(in []byte) []byte { | 
					
						
							|  |  |  | 	// In case of an invalid sig. Defaults to return nil | 
					
						
							|  |  |  | 	defer func() { recover() }() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-02 00:03:53 +01:00
										 |  |  | 	hash := in[:32] | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	v := common.BigD(in[32:64]).Bytes()[0] - 27 | 
					
						
							| 
									
										
										
										
											2014-12-02 00:03:53 +01:00
										 |  |  | 	sig := append(in[64:], v) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	return common.LeftPadBytes(crypto.Sha3(crypto.Ecrecover(append(hash, sig...))[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 | 
					
						
							|  |  |  | } |