resolver.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package resolver
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. "github.com/ethereum/go-ethereum/common"
  6. "github.com/ethereum/go-ethereum/core"
  7. "github.com/ethereum/go-ethereum/crypto"
  8. )
  9. /*
  10. Resolver implements the Ethereum DNS mapping
  11. HashReg : Key Hash (hash of domain name or contract code) -> Content Hash
  12. UrlHint : Content Hash -> Url Hint
  13. The resolver is meant to be called by the roundtripper transport implementation
  14. of a url scheme
  15. */
  16. const (
  17. URLHintContractAddress = core.ContractAddrURLhint
  18. HashRegContractAddress = core.ContractAddrHashReg
  19. )
  20. type Resolver struct {
  21. backend Backend
  22. urlHintContractAddress string
  23. hashRegContractAddress string
  24. }
  25. type Backend interface {
  26. StorageAt(string, string) string
  27. }
  28. func New(eth Backend, uhca, nrca string) *Resolver {
  29. return &Resolver{eth, uhca, nrca}
  30. }
  31. func (self *Resolver) KeyToContentHash(khash common.Hash) (chash common.Hash, err error) {
  32. // look up in hashReg
  33. key := storageAddress(1, khash[:])
  34. hash := self.backend.StorageAt("0x"+self.hashRegContractAddress, key)
  35. if hash == "0x0" || len(hash) < 3 {
  36. err = fmt.Errorf("GetHashReg: content hash not found")
  37. return
  38. }
  39. copy(chash[:], common.Hex2BytesFixed(hash[2:], 32))
  40. return
  41. }
  42. func (self *Resolver) ContentHashToUrl(chash common.Hash) (uri string, err error) {
  43. // look up in URL reg
  44. key := storageAddress(1, chash[:])
  45. hex := self.backend.StorageAt("0x"+self.urlHintContractAddress, key)
  46. uri = string(common.Hex2Bytes(hex[2:]))
  47. l := len(uri)
  48. for (l > 0) && (uri[l-1] == 0) {
  49. l--
  50. }
  51. uri = uri[:l]
  52. if l == 0 {
  53. err = fmt.Errorf("GetURLhint: URL hint not found")
  54. }
  55. return
  56. }
  57. func (self *Resolver) KeyToUrl(key common.Hash) (uri string, hash common.Hash, err error) {
  58. // look up in urlHint
  59. hash, err = self.KeyToContentHash(key)
  60. if err != nil {
  61. return
  62. }
  63. uri, err = self.ContentHashToUrl(hash)
  64. return
  65. }
  66. func storageAddress(varidx uint32, key []byte) string {
  67. data := make([]byte, 64)
  68. binary.BigEndian.PutUint32(data[60:64], varidx)
  69. copy(data[0:32], key[0:32])
  70. //fmt.Printf("%x %v\n", key, common.Bytes2Hex(crypto.Sha3(data)))
  71. return "0x" + common.Bytes2Hex(crypto.Sha3(data))
  72. }