| 
									
										
										
										
											2015-03-31 01:57:17 +01:00
										 |  |  | package resolver | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2015-03-31 16:02:55 +01:00
										 |  |  | 	"encoding/binary" | 
					
						
							| 
									
										
										
										
											2015-03-31 01:57:17 +01:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2015-03-31 16:02:55 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2015-04-14 15:20:52 +02:00
										 |  |  | 	xe "github.com/ethereum/go-ethereum/xeth" | 
					
						
							| 
									
										
										
										
											2015-03-31 01:57:17 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  | Resolver implements the Ethereum DNS mapping | 
					
						
							| 
									
										
										
										
											2015-04-07 11:50:17 +02:00
										 |  |  | HashReg : Key Hash (hash of domain name or contract code) -> Content Hash | 
					
						
							| 
									
										
										
										
											2015-03-31 01:57:17 +01:00
										 |  |  | UrlHint : Content Hash -> Url Hint | 
					
						
							| 
									
										
										
										
											2015-03-31 16:02:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | The resolver is meant to be called by the roundtripper transport implementation | 
					
						
							|  |  |  | of a url scheme | 
					
						
							| 
									
										
										
										
											2015-03-31 01:57:17 +01:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2015-04-14 15:20:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // contract addresses will be hardcoded after they're created | 
					
						
							|  |  |  | var URLHintContractAddress string = "0000000000000000000000000000000000000000000000000000000000001234" | 
					
						
							|  |  |  | var HashRegContractAddress string = "0000000000000000000000000000000000000000000000000000000000005678" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func CreateContracts(xeth *xe.XEth, addr string) { | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	URLHintContractAddress, err = xeth.Transact(addr, "", "100000000000", "1000000", "100000", ContractCodeURLhint) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		panic(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	HashRegContractAddress, err = xeth.Transact(addr, "", "100000000000", "1000000", "100000", ContractCodeHashReg) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		panic(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-03-31 01:57:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | type Resolver struct { | 
					
						
							| 
									
										
										
										
											2015-04-01 12:29:16 +01:00
										 |  |  | 	backend                Backend | 
					
						
							| 
									
										
										
										
											2015-03-31 16:02:55 +01:00
										 |  |  | 	urlHintContractAddress string | 
					
						
							| 
									
										
										
										
											2015-04-07 11:50:17 +02:00
										 |  |  | 	hashRegContractAddress string | 
					
						
							| 
									
										
										
										
											2015-03-31 16:02:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-01 12:29:16 +01:00
										 |  |  | type Backend interface { | 
					
						
							|  |  |  | 	StorageAt(string, string) string | 
					
						
							| 
									
										
										
										
											2015-03-31 01:57:17 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-01 12:29:16 +01:00
										 |  |  | func New(eth Backend, uhca, nrca string) *Resolver { | 
					
						
							|  |  |  | 	return &Resolver{eth, uhca, nrca} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 11:50:17 +02:00
										 |  |  | func (self *Resolver) KeyToContentHash(khash common.Hash) (chash common.Hash, err error) { | 
					
						
							|  |  |  | 	// look up in hashReg | 
					
						
							| 
									
										
										
										
											2015-04-17 13:46:38 +02:00
										 |  |  | 	key := storageAddress(storageMapping(storageIdx2Addr(1), khash[:])) | 
					
						
							| 
									
										
										
										
											2015-04-19 19:24:46 +01:00
										 |  |  | 	hash := self.backend.StorageAt(self.hashRegContractAddress, key) | 
					
						
							| 
									
										
										
										
											2015-04-07 11:50:17 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if hash == "0x0" || len(hash) < 3 { | 
					
						
							|  |  |  | 		err = fmt.Errorf("GetHashReg: content hash not found") | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	copy(chash[:], common.Hex2BytesFixed(hash[2:], 32)) | 
					
						
							| 
									
										
										
										
											2015-03-31 01:57:17 +01:00
										 |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-01 12:29:16 +01:00
										 |  |  | func (self *Resolver) ContentHashToUrl(chash common.Hash) (uri string, err error) { | 
					
						
							| 
									
										
										
										
											2015-04-07 11:50:17 +02:00
										 |  |  | 	// look up in URL reg | 
					
						
							| 
									
										
										
										
											2015-04-17 13:46:38 +02:00
										 |  |  | 	var str string = " " | 
					
						
							|  |  |  | 	var idx uint32 | 
					
						
							|  |  |  | 	for len(str) > 0 { | 
					
						
							|  |  |  | 		mapaddr := storageMapping(storageIdx2Addr(1), chash[:]) | 
					
						
							|  |  |  | 		key := storageAddress(storageFixedArray(mapaddr, storageIdx2Addr(idx))) | 
					
						
							| 
									
										
										
										
											2015-04-19 19:24:46 +01:00
										 |  |  | 		hex := self.backend.StorageAt(self.urlHintContractAddress, key) | 
					
						
							| 
									
										
										
										
											2015-04-17 13:46:38 +02:00
										 |  |  | 		str = string(common.Hex2Bytes(hex[2:])) | 
					
						
							|  |  |  | 		l := len(str) | 
					
						
							|  |  |  | 		for (l > 0) && (str[l-1] == 0) { | 
					
						
							|  |  |  | 			l-- | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		str = str[:l] | 
					
						
							|  |  |  | 		uri = uri + str | 
					
						
							|  |  |  | 		idx++ | 
					
						
							| 
									
										
										
										
											2015-03-31 16:02:55 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-01 12:29:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-17 13:46:38 +02:00
										 |  |  | 	if len(uri) == 0 { | 
					
						
							| 
									
										
										
										
											2015-03-31 16:02:55 +01:00
										 |  |  | 		err = fmt.Errorf("GetURLhint: URL hint not found") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							| 
									
										
										
										
											2015-03-31 01:57:17 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 11:50:17 +02:00
										 |  |  | func (self *Resolver) KeyToUrl(key common.Hash) (uri string, hash common.Hash, err error) { | 
					
						
							| 
									
										
										
										
											2015-03-31 01:57:17 +01:00
										 |  |  | 	// look up in urlHint | 
					
						
							| 
									
										
										
										
											2015-04-07 11:50:17 +02:00
										 |  |  | 	hash, err = self.KeyToContentHash(key) | 
					
						
							| 
									
										
										
										
											2015-03-31 01:57:17 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-31 16:02:55 +01:00
										 |  |  | 	uri, err = self.ContentHashToUrl(hash) | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-17 13:46:38 +02:00
										 |  |  | func storageIdx2Addr(varidx uint32) []byte { | 
					
						
							|  |  |  | 	data := make([]byte, 32) | 
					
						
							|  |  |  | 	binary.BigEndian.PutUint32(data[28:32], varidx) | 
					
						
							|  |  |  | 	return data | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func storageMapping(addr, key []byte) []byte { | 
					
						
							| 
									
										
										
										
											2015-03-31 16:02:55 +01:00
										 |  |  | 	data := make([]byte, 64) | 
					
						
							| 
									
										
										
										
											2015-04-06 08:01:36 +02:00
										 |  |  | 	copy(data[0:32], key[0:32]) | 
					
						
							| 
									
										
										
										
											2015-04-17 13:46:38 +02:00
										 |  |  | 	copy(data[32:64], addr[0:32]) | 
					
						
							|  |  |  | 	return crypto.Sha3(data) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func storageFixedArray(addr, idx []byte) []byte { | 
					
						
							|  |  |  | 	var carry byte | 
					
						
							|  |  |  | 	for i := 31; i >= 0; i-- { | 
					
						
							|  |  |  | 		var b byte = addr[i] + idx[i] + carry | 
					
						
							|  |  |  | 		if b < addr[i] { | 
					
						
							|  |  |  | 			carry = 1 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			carry = 0 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		addr[i] = b | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return addr | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func storageAddress(addr []byte) string { | 
					
						
							| 
									
										
										
										
											2015-04-19 19:24:46 +01:00
										 |  |  | 	return common.ToHex(addr) | 
					
						
							| 
									
										
										
										
											2015-03-31 01:57:17 +01:00
										 |  |  | } |