Skip to content

Commit

Permalink
[#10974] ENS resolving for IPNS names.
Browse files Browse the repository at this point in the history
  • Loading branch information
flexsurfer committed Sep 1, 2020
1 parent fdf8d11 commit 68f39ff
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 79 deletions.
13 changes: 6 additions & 7 deletions src/status_im/browser/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.ui.components.bottom-sheet.core :as bottom-sheet]
[status-im.browser.webview-ref :as webview-ref]
[alphabase.base58 :as alphabase.base58]
["eth-phishing-detect" :as eth-phishing-detect]
["hi-base32" :as hi-base32]))
["eth-phishing-detect" :as eth-phishing-detect]))

(fx/defn update-browser-option
[{:keys [db]} option-key option-value]
Expand Down Expand Up @@ -170,12 +168,13 @@

(defmulti storage-gateway :namespace)

(defmethod storage-gateway :ipns
[{:keys [hash]}]
hash)

(defmethod storage-gateway :ipfs
[{:keys [hash]}]
(let [base32hash (-> (.encode ^js hi-base32 (alphabase.base58/decode hash))
(string/replace #"=" "")
(string/lower-case))]
(str base32hash ".infura.status.im")))
(contenthash/ipfs-url hash))

(defmethod storage-gateway :swarm
[{:keys [hash]}]
Expand Down
81 changes: 31 additions & 50 deletions src/status_im/utils/contenthash.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -3,70 +3,51 @@
implementing swarm and other protocols will come later"
(:refer-clojure :exclude [cat])
(:require [alphabase.base58 :as b58]
["hi-base32" :as hi-base32]
[alphabase.hex :as hex]
[clojure.string :as string]
[status-im.ethereum.core :as ethereum]
[status-im.ipfs.core :as ipfs]
[status-im.utils.fx :as fx]))

(defn encode [{:keys [hash namespace ipld]}]
(when (and hash
(= namespace :ipfs)
(nil? ipld))
(when-let [b58-hash (if (string/starts-with? hash "z")
(when (= (count hash) 49)
;; this is a CID multihash
;; the z is removed, it indicates that the
;; CID is b58 encoded
(subs hash 1))
(when (= (count hash) 46)
;; this is a deprecated simple ipfs hash
hash))]
(str "0xe301" (hex/encode (b58/decode b58-hash))))))

(defn decode
"TODO properly decode the CID
extract the content-type using varint ns"
[hex]
(when (and hex (not= hex "0x"))
(cond
(and (string/starts-with? hex "0xe40101"))
;; content type can be 2 or 4 bytes
;; we expect 1b20 (hash algorithm keccak256 and hash length 64)
;; before the hash so we split the contenthash there
(when-let [hash (second (string/split hex "1b20"))]
{:namespace :swarm
:hash hash})
(and (= 78 (count hex))
(string/starts-with? hex "0xe3010170"))
;; for retrocompatibility with old CIDv0
{:namespace :ipfs
:hash (-> hex
(subs 10)
hex/decode
b58/encode)}
(and (= 78 (count hex))
(string/starts-with? hex "0xe30101"))
;; new CIDv1
{:namespace :ipfs
:hash (str "z" (-> hex
(subs 6)
hex/decode
b58/encode))})))
(let [result (when (and hex (not= hex "0x"))
(cond
(and (string/starts-with? hex "0xe40101"))
;; content type can be 2 or 4 bytes
;; we expect 1b20 (hash algorithm keccak256 and hash length 64)
;; before the hash so we split the contenthash there
(when-let [hash (second (string/split hex "1b20"))]
{:namespace :swarm
:hash hash})
(and (= 78 (count hex))
(string/starts-with? hex "0xe3010170"))
{:namespace :ipfs
:hash (str "b" (-> hex
(subs 6)
hex/decode
((fn [v] (.encode ^js hi-base32 v)))
(string/replace #"=" "")
string/lower-case))}
(and (string/starts-with? hex "0xe50101700"))
{:namespace :ipns
:hash (-> hex
(subs 14)
((fn [v] (str "0x" v)))
(ethereum/hex-to-utf8))}))]
(println "RESULT" hex result)
result))

(defn ipfs-url [hash]
(str "https://" hash ".ipfs.cf-ipfs.com"))

(defn url-fn [hex]
(let [{:keys [namespace hash]} (decode (ethereum/normalized-hex hex))]
(case namespace
:ipfs (str "https://ipfs.infura.io/ipfs/" hash)
:ipfs (ipfs-url hash)
"")))

(def url (memoize url-fn))

(fx/defn cat
[cofx {:keys [contenthash on-success on-failure]}]
(let [{:keys [namespace hash]} (decode contenthash)]
(when (= namespace :ipfs)
(ipfs/cat cofx
{:hash hash
:on-success on-success
:on-failure on-failure}))))
28 changes: 6 additions & 22 deletions src/status_im/utils/contenthash_test.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
(testing "decoding a valid ipfs hash"
(is (= (contenthash/decode "0xe3010170122029f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f")
{:namespace :ipfs
:hash "QmRAQB6YaCyidP37UdDnjFY5vQuiBrcqdyoW1CuDgwxkD4"})))
:hash "bafybeibj6lixxzqtsb45ysdjnupvqkufgdvzqbnvmhw2kf7cfkesy7r7d4"})))
(testing "decoding a valid ipns hash"
(is (= (contenthash/decode "0xe5010170000f6170702e756e69737761702e6f7267")
{:namespace :ipns
:hash "app.uniswap.org"})))
(testing "decoding a valid swarm hash"
(is (= (contenthash/decode "0xe40101fa011b20d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162")
{:namespace :swarm
Expand All @@ -19,24 +23,4 @@
(testing "decoding random garbage"
(is (nil? (contenthash/decode "0xabcdef1234567890"))))
(testing "decoding nil"
(is (nil? (contenthash/decode nil)))))

(deftest contenthash-encode
(testing "encoding a valid ipfs hash"
(is (= (contenthash/encode
{:namespace :ipfs
:hash "QmRAQB6YaCyidP37UdDnjFY5vQuiBrcqdyoW1CuDgwxkD4"})
"0xe301122029f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f")))
(testing "encoding a valid ipfs cid"
(is (= (contenthash/encode
{:namespace :ipfs
:hash "zb2rhZfjRh2FHHB2RkHVEvL2vJnCTcu7kwRqgVsf9gpkLgteo"})
"0xe301015512202cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824")))
(testing "encoding an invalid ipfs hash"
(is (nil? (contenthash/encode {:namespace :ipfs
:hash "0xe301122029f2d17be6139079dc48696d1f582a8530eb9805b561eda517e2"}))))
(testing "encoding random garbage"
(is (nil? (contenthash/encode {:namespace :ipfs
:hash "0xabcdef1234567890"}))))
(testing "encoding random garbage"
(is (nil? (contenthash/encode nil)))))
(is (nil? (contenthash/decode nil)))))

0 comments on commit 68f39ff

Please sign in to comment.