Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verify ENS names #9178

Merged
merged 1 commit into from
Oct 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 30 additions & 8 deletions src/status_im/contact/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,11 @@
{:db (assoc-in db [:contacts/new-identity] "")}
(upsert-contact contact)))))

(defn handle-contact-update
[public-key
(fx/defn handle-contact-update
[{{:contacts/keys [contacts] :as db} :db :as cofx}
public-key
timestamp
{:keys [name profile-image address fcm-token device-info] :as m}
{{:contacts/keys [contacts] :as db} :db :as cofx}]
{:keys [name profile-image address fcm-token device-info] :as m}]
;; We need to convert to timestamp ms as before we were using now in ms to
;; set last updated
;; Using whisper timestamp mostly works but breaks in a few scenarios:
Expand Down Expand Up @@ -139,10 +139,6 @@
fcm-token (assoc :fcm-token fcm-token))]
(upsert-contact cofx contact-props)))))

(def receive-contact-request handle-contact-update)
(def receive-contact-request-confirmation handle-contact-update)
(def receive-contact-update handle-contact-update)

(fx/defn initialize-contacts [cofx]
(contacts-store/fetch-contacts-rpc cofx #(re-frame/dispatch [::contacts-loaded %])))

Expand All @@ -161,3 +157,29 @@
(assoc :tribute-to-talk (or tribute-to-talk
{:disabled? true})))]
{:db (assoc-in db [:contacts/contacts public-key] contact)}))

(defn add-ens-names [contacts names]
(reduce-kv (fn [acc public-key-keyword result]
(let [verified (:verified result)
error (:error result)
ens-name (:name result)
ens-verified-at (:verifiedAt result)
public-key (str "0x" (name public-key-keyword))
contact (contact.db/public-key->contact contacts public-key)]

(if error
(assoc acc public-key contact)
(assoc acc public-key
(assoc contact
;; setting the name for now as ens-verification is not enabled because of geth 1.9 upgrade
:name ens-name
:ens-verified-at ens-verified-at
:ens-verified verified)))))
(or contacts {})
names))

(fx/defn names-verified
{:events [:contacts/ens-names-verified]}
[{:keys [db]} names]
{:db (update db :contacts/contacts add-ens-names names)})

14 changes: 9 additions & 5 deletions src/status_im/contact/db.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
(spec/def :contact/last-online (spec/nilable int?))
(spec/def :contact/last-updated (spec/nilable int?))
(spec/def :contact/name (spec/nilable string?))
(spec/def :contact/ens-verified (spec/nilable boolean?))
(spec/def :contact/ens-verified-at (spec/nilable int?))
(spec/def :contact/public-key :global/not-empty-string)
(spec/def :contact/photo-path (spec/nilable string?))

Expand Down Expand Up @@ -63,11 +65,13 @@
(spec/def :ui/contact (spec/keys :opt [:contact/new-tag]))

(defn public-key->new-contact [public-key]
{:name (gfycat/generate-gfy public-key)
:address (ethereum/public-key->address public-key)
:identicon (identicon/identicon public-key)
:public-key public-key
:system-tags #{}})
(let [alias (gfycat/generate-gfy public-key)]
{:alias alias
:name alias
:address (ethereum/public-key->address public-key)
:identicon (identicon/identicon public-key)
:public-key public-key
:system-tags #{}}))

(defn public-key->contact
[contacts public-key]
Expand Down
4 changes: 4 additions & 0 deletions src/status_im/data_store/contacts.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
:photoPath :photo-path
:deviceInfo :device-info
:tributeToTalk :tribute-to-talk
:ensVerifiedAt :ens-verified-at
:ensVerified :ens-verified
:systemTags :system-tags
:lastUpdated :last-updated})))

Expand All @@ -42,6 +44,8 @@
(update :tribute-to-talk types/serialize)
(update :system-tags #(mapv str %))
(clojure.set/rename-keys {:public-key :id
:ens-verified :ensVerified
:ens-verified-at :ensVerifiedAt
:photo-path :photoPath
:device-info :deviceInfo
:tribute-to-talk :tributeToTalk
Expand Down
32 changes: 32 additions & 0 deletions src/status_im/ens/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.ens.db :as ens.db]
[taoensso.timbre :as log]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.multiaccounts.model :as multiaccounts.model]
[status-im.ethereum.abi-spec :as abi-spec]
[status-im.ethereum.contracts :as contracts]
[status-im.ethereum.core :as ethereum]
Expand All @@ -11,6 +14,7 @@
[status-im.ethereum.stateofus :as stateofus]
[status-im.ui.screens.navigation :as navigation]
[status-im.utils.fx :as fx]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.utils.money :as money]
[status-im.signing.core :as signing]
[status-im.multiaccounts.update.core :as multiaccounts.update]
Expand Down Expand Up @@ -252,3 +256,31 @@
(fx/merge cofx
(set-username-candidate (get-in db [:ens/registration :username] ""))
(navigation/navigate-to-cofx :ens-search {})))

(defn verify-names [names]
(json-rpc/call {:method "shhext_verifyENSNames"
:params [names]
:on-success #(re-frame/dispatch [:contacts/ens-names-verified %])
:on-failure #(log/error "failed to resolve ens names" % names)}))

(re-frame/reg-fx
::verify-names
(fn [names]
(verify-names (distinct names))))

(defn should-be-verified? [cofx ens-name signature]
(and ens-name
(not (get-in cofx [:contacts/contacts signature :ens-verified]))
(not= signature (multiaccounts.model/current-public-key cofx))
(or (valid-custom-domain? ens-name)
(stateofus/valid-username? ens-name))))

(fx/defn verify-names-from-message [cofx {:keys [content]} signature]
(when (should-be-verified? cofx (:name content) signature)
{::verify-names [{:name (:name content)
:publicKey (subs signature 2)}]}))

(fx/defn verify-names-from-contact-request [cofx {:keys [name]} signature]
(when (should-be-verified? cofx name signature)
{::verify-names [{:name name
:publicKey (subs signature 2)}]}))
1 change: 1 addition & 0 deletions src/status_im/ethereum/json_rpc.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
;;TODO not used anywhere?
"shhext_deleteChat" {}
"shhext_saveContact" {}
"shhext_verifyENSNames" {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this would entirely be done on go side?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, eventually maybe, but we are not parsing messages yet in status-go (we only do for the console client, but otherwise we would be parsing them twice, as we still have to port some of the handling, so it's disabled in status-react), and the ens name is inside the content field (or contact-request).
So status-react will parse the message and send the usernames to be verified to status-go (note that even if we did resolve them in status-go, it would be asynchronous, as resolving username can take up to 1,2 seconds, so we would pass the messages immediately and send another signal once resolved, so from a user perspective it would be asynchronous in both cases)

"status_chats" {}
"wallet_getTransfers" {}
"wallet_getTokensBalances" {}
Expand Down
23 changes: 15 additions & 8 deletions src/status_im/multiaccounts/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,23 @@
[status-im.utils.platform :as platform]
[status-im.utils.utils :as utils]))

; Whether we should be strict about verifying ens, currently disabled as
; status-go can't be upgrade because of geth 1.9 incompatibility
(def only-verified-ens false)
(defn displayed-name
"Use preferred name, name or alias in that order"
[{:keys [name preferred-name alias public-key]}]
(let [name (or preferred-name
name
alias)]
(if (ens/is-valid-eth-name? name)
(let [username (stateofus/username name)]
(str "@" (or username name)))
(or name (gfycat/generate-gfy public-key)))))
[{:keys [name preferred-name alias public-key ens-verified]}]
(let [ens-name (or preferred-name
name)]
;; Preferred name is our own
;; otherwise we make sure is verified
(if (or preferred-name
(and only-verified-ens
ens-verified
name))
(let [username (stateofus/username ens-name)]
(str "@" (or username ens-name)))
(or alias (gfycat/generate-gfy public-key)))))

(defn displayed-photo
"If a photo-path is set use it, otherwise fallback on identicon or generate"
Expand Down
5 changes: 3 additions & 2 deletions src/status_im/subs.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -1583,11 +1583,12 @@
(fn [[contacts current-multiaccount] [_ identity]]
(let [me? (= (:public-key current-multiaccount) identity)]
(if me?
{:username (:name current-multiaccount)
{:ens-name (:name current-multiaccount)
:alias (gfycat/generate-gfy identity)}
(let [contact (or (contacts identity)
(contact.db/public-key->new-contact identity))]
{:username (:name contact)
{:ens-name (when (:ens-verified contact)
(:name contact))
:alias (or (:alias contact)
(gfycat/generate-gfy identity))})))))

Expand Down
26 changes: 23 additions & 3 deletions src/status_im/transport/impl/receive.cljs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
(ns status-im.transport.impl.receive
(:require [status-im.group-chats.core :as group-chats]
[status-im.contact.core :as contact]
[status-im.utils.fx :as fx]
[status-im.ens.core :as ens]
[status-im.pairing.core :as pairing]
[status-im.transport.message.contact :as transport.contact]
[status-im.transport.message.group-chat :as transport.group-chat]
[status-im.transport.message.pairing :as transport.pairing]
[status-im.transport.message.core :as transport.message]

[status-im.transport.message.protocol :as protocol]))

(extend-type transport.group-chat/GroupMembershipUpdate
Expand All @@ -16,17 +20,26 @@
(extend-type transport.contact/ContactRequest
protocol/StatusMessage
(receive [this _ signature timestamp cofx]
(contact/receive-contact-request signature timestamp this cofx)))
(fx/merge
cofx
(contact/handle-contact-update cofx signature timestamp this)
(ens/verify-names-from-contact-request this signature))))

(extend-type transport.contact/ContactRequestConfirmed
protocol/StatusMessage
(receive [this _ signature timestamp cofx]
(contact/receive-contact-request-confirmation signature timestamp this cofx)))
(fx/merge
cofx
(contact/handle-contact-update cofx signature timestamp this)
(ens/verify-names-from-contact-request this signature))))

(extend-type transport.contact/ContactUpdate
protocol/StatusMessage
(receive [this _ signature timestamp cofx]
(contact/receive-contact-update signature timestamp this cofx)))
(fx/merge
cofx
(contact/handle-contact-update cofx signature timestamp this)
(ens/verify-names-from-contact-request this signature))))

(extend-type transport.pairing/SyncInstallation
protocol/StatusMessage
Expand All @@ -37,3 +50,10 @@
protocol/StatusMessage
(receive [this _ signature timestamp cofx]
(pairing/handle-pair-installation cofx this timestamp signature)))

(extend-type protocol/Message
protocol/StatusMessage
(receive [this chat-id signature timestamp cofx]
(fx/merge cofx
(transport.message/receive-transit-message this chat-id signature timestamp)
(ens/verify-names-from-message this signature))))
19 changes: 19 additions & 0 deletions src/status_im/transport/message/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
[status-im.transport.message.protocol :as protocol]
[status-im.transport.message.transit :as transit]
[status-im.transport.utils :as transport.utils]
[status-im.tribute-to-talk.whitelist :as whitelist]
[status-im.utils.config :as config]
[status-im.utils.fx :as fx]
[taoensso.timbre :as log]
Expand Down Expand Up @@ -180,3 +181,21 @@
:params [confirmations]
:on-success #(log/debug "successfully confirmed messages")
:on-failure #(log/error "failed to confirm messages" %)}))))

(fx/defn receive-transit-message [cofx message chat-id signature timestamp]
(let [received-message-fx {:chat-received-message/add-fx
[(assoc (into {} message)
:message-id
(get-in cofx [:metadata :messageId])
:chat-id chat-id
:whisper-timestamp timestamp
:alias (get-in cofx [:metadata :author :alias])
:identicon (get-in cofx [:metadata :author :identicon])
:from signature
:metadata (:metadata cofx)
:js-obj (:js-obj cofx))]}]
(whitelist/filter-message cofx
received-message-fx
(:message-type message)
(get-in message [:content :tribute-transaction])
signature)))
22 changes: 0 additions & 22 deletions src/status_im/transport/message/protocol.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -70,28 +70,6 @@
(when (pairing.utils/has-paired-installations? cofx)
(send-direct-message current-public-key nil this))
(send-with-pubkey params)))))
(receive [this chat-id signature timestamp cofx]
(let [received-message-fx {:chat-received-message/add-fx
[(assoc (into {} this)
:message-id
(or (get-in cofx [:metadata :messageId])
(transport.utils/message-id
signature
(.-payload (:js-obj cofx))))
:chat-id chat-id
:whisper-timestamp timestamp
:raw-payload-hash (ethereum/sha3
(.-payload (:js-obj cofx)))
:alias (get-in cofx [:metadata :author :alias])
:identicon (get-in cofx [:metadata :author :identicon])
:from signature
:metadata (:metadata cofx)
:js-obj (:js-obj cofx))]}]
(whitelist/filter-message cofx
received-message-fx
message-type
(get-in this [:content :tribute-transaction])
signature)))
(validate [this]
(if (spec/valid? :message/message this)
this
Expand Down
4 changes: 2 additions & 2 deletions src/status_im/ui/screens/chat/input/input.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,14 @@
:color colors/gray}]]])))

(defview reply-message [from alias message-text]
(letsubs [{:keys [username]} [:contacts/contact-name-by-identity from]
(letsubs [{:keys [ens-name]} [:contacts/contact-name-by-identity from]
current-public-key [:multiaccount/public-key]]
[react/scroll-view {:style style/reply-message-content}
[react/view {:style style/reply-message-to-container}
[vector-icons/tiny-icon :tiny-icons/tiny-reply {:container-style style/reply-icon
:width 20
:color colors/gray}]
(chat-utils/format-reply-author from alias username current-public-key style/reply-message-author)]
(chat-utils/format-reply-author from alias ens-name current-public-key style/reply-message-author)]
[react/text {:style (assoc (message-style/style-message-text false) :font-size 14) :number-of-lines 3} message-text]]))

(defview reply-message-view []
Expand Down
11 changes: 6 additions & 5 deletions src/status_im/ui/screens/chat/message/message.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@
content content-type]])

(defview quoted-message [{:keys [from text]} outgoing current-public-key]
(letsubs [{:keys [username alias]} [:contacts/contact-name-by-identity from]]
(letsubs [{:keys [ens-name alias]} [:contacts/contact-name-by-identity from]]
[react/view {:style (style/quoted-message-container outgoing)}
[react/view {:style style/quoted-message-author-container}
[vector-icons/tiny-icon :tiny-icons/tiny-reply {:color (if outgoing colors/white-transparent colors/gray)}]
(chat.utils/format-reply-author from alias username current-public-key (partial style/quoted-message-author outgoing))]
(chat.utils/format-reply-author from alias ens-name current-public-key (partial style/quoted-message-author outgoing))]

[react/text {:style (style/quoted-message-text outgoing)
:number-of-lines 5}
Expand Down Expand Up @@ -196,8 +196,9 @@
(:command content))
[command-status content]))))

(defview message-author-name [alias name]
(chat.utils/format-author alias style/message-author-name name))
(defview message-author-name [from alias]
(letsubs [{:keys [ens-name]} [:contacts/contact-name-by-identity from]]
(chat.utils/format-author alias style/message-author-name ens-name)))

(defn message-body
[{:keys [last-in-group?
Expand All @@ -219,7 +220,7 @@
[react/view (style/group-message-view outgoing display-photo?)
(when display-username?
[react/touchable-opacity {:on-press #(re-frame/dispatch [:chat.ui/show-profile from])}
[message-author-name alias (:name content)]])
[message-author-name from alias]])
[react/view {:style (style/timestamp-content-wrapper outgoing)}
child]]]
[react/view (style/delivery-status outgoing)
Expand Down
2 changes: 1 addition & 1 deletion src/status_im/ui/screens/chat/utils.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

(defn format-author [alias style name]
(let [additional-styles (style false)]
(if (ens/is-valid-eth-name? name)
(if name
[react/text {:style (merge {:color colors/blue :font-size 13 :font-weight "500"} additional-styles)}
(str "@" (or (stateofus/username name) name))]
[react/text {:style (merge {:color colors/gray :font-size 12 :font-weight "400"} additional-styles)}
Expand Down
Loading