Skip to content

Commit

Permalink
Verify ens names on messages and contact requests
Browse files Browse the repository at this point in the history
This commits verifies ens names when new messages or contact requests
come through.
A batch of ens names is sent to status-go which will then verifying them
and the result will be passed back in a callback to status-react.
  • Loading branch information
cammellos committed Oct 23, 2019
1 parent 474ff00 commit eff12db
Show file tree
Hide file tree
Showing 19 changed files with 227 additions and 99 deletions.
43 changes: 35 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,34 @@
(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)]

(cond error
(assoc acc public-key contact)
verified
(assoc acc public-key (assoc
contact
:name ens-name
:ens-verified-at ens-verified-at
:ens-verified true))
:else
(assoc acc public-key (assoc
contact
:ens-verified-at ens-verified-at
:ens-verified false)))))
(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" {}
"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

0 comments on commit eff12db

Please sign in to comment.