aboutsummaryrefslogtreecommitdiffstats
path: root/common/resolver/resolver.go
diff options
context:
space:
mode:
Diffstat (limited to 'common/resolver/resolver.go')
-rw-r--r--common/resolver/resolver.go154
1 files changed, 129 insertions, 25 deletions
diff --git a/common/resolver/resolver.go b/common/resolver/resolver.go
index 42348a89c..9016547e1 100644
--- a/common/resolver/resolver.go
+++ b/common/resolver/resolver.go
@@ -6,7 +6,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
- xe "github.com/ethereum/go-ethereum/xeth"
+ "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/logger/glog"
)
/*
@@ -18,50 +19,152 @@ The resolver is meant to be called by the roundtripper transport implementation
of a url scheme
*/
-// contract addresses will be hardcoded after they're created
-var URLHintContractAddress string = "0000000000000000000000000000000000000000000000000000000000001234"
-var HashRegContractAddress string = "0000000000000000000000000000000000000000000000000000000000005678"
+// // contract addresses will be hardcoded after they're created
+var UrlHintContractAddress, HashRegContractAddress string
-func CreateContracts(xeth *xe.XEth, addr string) {
- var err error
- URLHintContractAddress, err = xeth.Transact(addr, "", "", "100000000000", "1000000", "100000", ContractCodeURLhint)
+const (
+ txValue = "0"
+ txGas = "100000"
+ txGasPrice = "1000000000000"
+)
+
+func abi(s string) string {
+ return common.ToHex(crypto.Sha3([]byte(s))[:4])
+}
+
+var (
+ registerContentHashAbi = abi("register(uint256,uint256)")
+ registerUrlAbi = abi("register(uint256,uint8,uint256)")
+ setOwnerAbi = abi("setowner()")
+)
+
+type Backend interface {
+ StorageAt(string, string) string
+ Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error)
+}
+
+type Resolver struct {
+ backend Backend
+}
+
+func New(eth Backend) *Resolver {
+ return &Resolver{eth}
+}
+
+// for testing and play temporarily
+// ideally the HashReg and UrlHint contracts should be in the genesis block
+// if we got build-in support for natspec/contract info
+// there should be only one of these officially endorsed
+// addresses as constants
+// TODO: could get around this with namereg, check
+func (self *Resolver) CreateContracts(addr common.Address) (err error) {
+ HashRegContractAddress, err = self.backend.Transact(addr.Hex(), "", "", txValue, txGas, txGasPrice, ContractCodeHashReg)
if err != nil {
- panic(err)
+ return
}
- HashRegContractAddress, err = xeth.Transact(addr, "", "", "100000000000", "1000000", "100000", ContractCodeHashReg)
+ UrlHintContractAddress, err = self.backend.Transact(addr.Hex(), "", "", txValue, txGas, txGasPrice, ContractCodeURLhint)
+ glog.V(logger.Detail).Infof("HashReg @ %v\nUrlHint @ %v\n", HashRegContractAddress, UrlHintContractAddress)
+ return
+}
+
+// called as first step in the registration process on HashReg
+func (self *Resolver) SetOwner(address common.Address) (txh string, err error) {
+ return self.backend.Transact(
+ address.Hex(),
+ HashRegContractAddress,
+ "", txValue, txGas, txGasPrice,
+ setOwnerAbi,
+ )
+}
+
+// registers some content hash to a key/code hash
+// e.g., the contract Info combined Json Doc's ContentHash
+// to CodeHash of a contract or hash of a domain
+// kept
+func (self *Resolver) RegisterContentHash(address common.Address, codehash, dochash common.Hash) (txh string, err error) {
+ _, err = self.SetOwner(address)
if err != nil {
- panic(err)
+ return
}
+ codehex := common.Bytes2Hex(codehash[:])
+ dochex := common.Bytes2Hex(dochash[:])
+
+ data := registerContentHashAbi + codehex + dochex
+ return self.backend.Transact(
+ address.Hex(),
+ HashRegContractAddress,
+ "", txValue, txGas, txGasPrice,
+ data,
+ )
}
-type Resolver struct {
- backend Backend
- urlHintContractAddress string
- hashRegContractAddress string
+// registers a url to a content hash so that the content can be fetched
+// address is used as sender for the transaction and will be the owner of a new
+// registry entry on first time use
+// FIXME: silently doing nothing if sender is not the owner
+// note that with content addressed storage, this step is no longer necessary
+// it could be purely
+func (self *Resolver) RegisterUrl(address common.Address, hash common.Hash, url string) (txh string, err error) {
+ hashHex := common.Bytes2Hex(hash[:])
+ var urlHex string
+ urlb := []byte(url)
+ var cnt byte
+ n := len(urlb)
+
+ for n > 0 {
+ if n > 32 {
+ n = 32
+ }
+ urlHex = common.Bytes2Hex(urlb[:n])
+ urlb = urlb[n:]
+ n = len(urlb)
+ bcnt := make([]byte, 32)
+ bcnt[31] = cnt
+ data := registerUrlAbi +
+ hashHex +
+ common.Bytes2Hex(bcnt) +
+ common.Bytes2Hex(common.Hex2BytesFixed(urlHex, 32))
+ txh, err = self.backend.Transact(
+ address.Hex(),
+ UrlHintContractAddress,
+ "", txValue, txGas, txGasPrice,
+ data,
+ )
+ if err != nil {
+ return
+ }
+ cnt++
+ }
+ return
}
-type Backend interface {
- StorageAt(string, string) string
-}
+func (self *Resolver) Register(address common.Address, codehash, dochash common.Hash, url string) (txh string, err error) {
-func New(eth Backend, uhca, nrca string) *Resolver {
- return &Resolver{eth, uhca, nrca}
+ _, err = self.RegisterContentHash(address, codehash, dochash)
+ if err != nil {
+ return
+ }
+ return self.RegisterUrl(address, dochash, url)
}
+// resolution is costless non-transactional
+// implemented as direct retrieval from db
func (self *Resolver) KeyToContentHash(khash common.Hash) (chash common.Hash, err error) {
// look up in hashReg
+ at := common.Bytes2Hex(common.FromHex(HashRegContractAddress))
key := storageAddress(storageMapping(storageIdx2Addr(1), khash[:]))
- hash := self.backend.StorageAt(self.hashRegContractAddress, key)
+ hash := self.backend.StorageAt(at, key)
if hash == "0x0" || len(hash) < 3 {
- err = fmt.Errorf("GetHashReg: content hash not found")
+ err = fmt.Errorf("content hash not found for '%v'", khash.Hex())
return
}
-
copy(chash[:], common.Hex2BytesFixed(hash[2:], 32))
return
}
+// retrieves the url-hint for the content hash -
+// if we use content addressed storage, this step is no longer necessary
func (self *Resolver) ContentHashToUrl(chash common.Hash) (uri string, err error) {
// look up in URL reg
var str string = " "
@@ -69,7 +172,7 @@ func (self *Resolver) ContentHashToUrl(chash common.Hash) (uri string, err error
for len(str) > 0 {
mapaddr := storageMapping(storageIdx2Addr(1), chash[:])
key := storageAddress(storageFixedArray(mapaddr, storageIdx2Addr(idx)))
- hex := self.backend.StorageAt(self.urlHintContractAddress, key)
+ hex := self.backend.StorageAt(UrlHintContractAddress, key)
str = string(common.Hex2Bytes(hex[2:]))
l := len(str)
for (l > 0) && (str[l-1] == 0) {
@@ -81,7 +184,7 @@ func (self *Resolver) ContentHashToUrl(chash common.Hash) (uri string, err error
}
if len(uri) == 0 {
- err = fmt.Errorf("GetURLhint: URL hint not found")
+ err = fmt.Errorf("GetURLhint: URL hint not found for '%v'", chash.Hex())
}
return
}
@@ -106,7 +209,8 @@ func storageMapping(addr, key []byte) []byte {
data := make([]byte, 64)
copy(data[0:32], key[0:32])
copy(data[32:64], addr[0:32])
- return crypto.Sha3(data)
+ sha := crypto.Sha3(data)
+ return sha
}
func storageFixedArray(addr, idx []byte) []byte {