From 9462088de8b50ab265290d33ac943b17064895c6 Mon Sep 17 00:00:00 2001 From: alwx Date: Mon, 2 Jan 2017 18:45:39 +0300 Subject: [PATCH] Update public/private keys for discoveries (#557) --- src/status_im/accounts/handlers.cljs | 42 +++++++++++++++---- src/status_im/contacts/handlers.cljs | 32 ++++++++++---- .../realm/schemas/account/v1/contact.cljs | 37 ++++++++-------- src/status_im/discover/handlers.cljs | 10 +---- src/status_im/protocol/core.cljs | 1 + src/status_im/protocol/discoveries.cljs | 22 +++++++++- src/status_im/protocol/handlers.cljs | 1 + src/status_im/protocol/message.cljs | 2 +- src/status_im/utils/handlers.cljs | 6 +++ 9 files changed, 110 insertions(+), 43 deletions(-) diff --git a/src/status_im/accounts/handlers.cljs b/src/status_im/accounts/handlers.cljs index b671f2ef3b..6b5bfbbdce 100644 --- a/src/status_im/accounts/handlers.cljs +++ b/src/status_im/accounts/handlers.cljs @@ -71,7 +71,7 @@ account' (assoc account :network (or acc-network network))] (accounts-store/save account' true))) -(defn send-account-update +(defn broadcast-account-update [{:keys [current-account-id current-public-key web3 accounts]} _] (let [{:keys [name photo-path status]} (get accounts current-account-id) {:keys [updates-public-key updates-private-key]} (accounts current-account-id)] @@ -85,6 +85,19 @@ :status status :profile-image photo-path}}}}))) +(defn send-keys-update + [{:keys [current-account-id current-public-key web3 accounts contacts]} _] + (let [{:keys [name photo-path status]} (get accounts current-account-id) + {:keys [updates-public-key updates-private-key]} (accounts current-account-id)] + (doseq [id (u/identities contacts)] + (protocol/update-keys! + {:web3 web3 + :message {:from current-public-key + :to id + :message-id (random/id) + :payload {:keypair {:public updates-public-key + :private updates-private-key}}}})))) + (register-handler :check-status-change (u/side-effect! @@ -97,14 +110,27 @@ (when (seq hashtags) (dispatch [:broadcast-status status hashtags])))))))) +(defn account-update + [{:keys [current-account-id accounts] :as db} data] + (let [data (assoc data :last-updated (time/now-ms)) + account (merge (get accounts current-account-id) data)] + (assoc-in db [:accounts current-account-id] account))) + (register-handler - :account-update - (-> (fn [{:keys [current-account-id accounts] :as db} [_ data]] - (let [data (assoc data :last-updated (time/now-ms)) - account (merge (get accounts current-account-id) data)] - (assoc-in db [:accounts current-account-id] account))) - ((after save-account!)) - ((after send-account-update)))) + :account-update + (-> (fn [db [_ data]] + (account-update db data)) + ((after save-account!)) + ((after broadcast-account-update)))) + +(register-handler + :account-update-keys + (-> (fn [db] + (let [{:keys [public private]} (protocol/new-keypair!)] + (account-update db {:updates-public-key public + :updates-private-key private}))) + ((after save-account!)) + ((after send-keys-update)))) (register-handler :send-account-update-if-needed diff --git a/src/status_im/contacts/handlers.cljs b/src/status_im/contacts/handlers.cljs index e1a959a698..1292bfb08d 100644 --- a/src/status_im/contacts/handlers.cljs +++ b/src/status_im/contacts/handlers.cljs @@ -231,14 +231,15 @@ (register-handler :set-contact-identity-from-qr set-contact-identity-from-qr) -(register-handler :contact-update-received +(register-handler + :contact-update-received (u/side-effect! (fn [{:keys [chats current-public-key] :as db} [_ {:keys [from payload]}]] (when (not= current-public-key from) (let [{:keys [content timestamp]} payload {:keys [status name profile-image]} (:profile content) prev-last-updated (get-in db [:contacts from :last-updated])] - (if (<= prev-last-updated timestamp) + (when (<= prev-last-updated timestamp) (let [contact {:whisper-identity from :name name :photo-path profile-image @@ -249,12 +250,27 @@ (dispatch [:update-chat! {:chat-id from :name name}]))))))))) -(register-handler :contact-online-received +(register-handler + :update-keys-received + (u/side-effect! + (fn [db [_ {:keys [from payload]}]] + (let [{{:keys [public private]} :keypair + timestamp :timestamp} payload + prev-last-updated (get-in db [:contacts from :keys-last-updated])] + (when (<= prev-last-updated timestamp) + (let [contact {:whisper-identity from + :public-key public + :private-key private + :keys-last-updated timestamp}] + (dispatch [:update-contact! contact]))))))) + +(register-handler + :contact-online-received (u/side-effect! (fn [db [_ {:keys [from] - {:keys [timestamp]} :payload}]] + {{:keys [timestamp]} :content} :payload}]] (let [prev-last-online (get-in db [:contacts from :last-online])] - (when (< prev-last-online timestamp) + (when (and timestamp (< prev-last-online timestamp)) (protocol/reset-pending-messages! from) (dispatch [:update-contact! {:whisper-identity from :last-online timestamp}])))))) @@ -265,9 +281,11 @@ (fn [_ [_ {:keys [whisper-identity] :as contact}]] (dispatch [:update-chat! {:chat-id whisper-identity :pending-contact? true}]) - (dispatch [:update-contact! (assoc contact :pending true)])))) + (dispatch [:update-contact! (assoc contact :pending true)]) + (dispatch [:account-update-keys])))) -(register-handler :open-contact-menu +(register-handler + :open-contact-menu (u/side-effect! (fn [_ [_ list-selection-fn {:keys [name] :as contact}]] (list-selection-fn {:title name diff --git a/src/status_im/data_store/realm/schemas/account/v1/contact.cljs b/src/status_im/data_store/realm/schemas/account/v1/contact.cljs index 929c807f89..9c5b4c7eb7 100644 --- a/src/status_im/data_store/realm/schemas/account/v1/contact.cljs +++ b/src/status_im/data_store/realm/schemas/account/v1/contact.cljs @@ -3,24 +3,25 @@ (def schema {:name :contact :primaryKey :whisper-identity - :properties {:address {:type "string" :optional true} - :whisper-identity "string" - :name {:type "string" :optional true} - :photo-path {:type "string" :optional true} - :last-updated {:type "int" :default 0} - :last-online {:type "int" :default 0} - :pending {:type "bool" :default false} - :status {:type "string" :optional true} - :public-key {:type :string - :optional true} - :private-key {:type :string - :optional true} - :dapp? {:type :bool - :default false} - :dapp-url {:type :string - :optional true} - :dapp-hash {:type :int - :optional true}}}) + :properties {:address {:type "string" :optional true} + :whisper-identity "string" + :name {:type "string" :optional true} + :photo-path {:type "string" :optional true} + :last-updated {:type "int" :default 0} + :last-online {:type "int" :default 0} + :pending {:type "bool" :default false} + :status {:type "string" :optional true} + :public-key {:type :string + :optional true} + :private-key {:type :string + :optional true} + :keys-last-updated {:type "int" :default 0} + :dapp? {:type :bool + :default false} + :dapp-url {:type :string + :optional true} + :dapp-hash {:type :int + :optional true}}}) (defn migration [_ _] (log/debug "migrating contact schema")) diff --git a/src/status_im/discover/handlers.cljs b/src/status_im/discover/handlers.cljs index 3e2a783242..c9f1f6e1ac 100644 --- a/src/status_im/discover/handlers.cljs +++ b/src/status_im/discover/handlers.cljs @@ -17,12 +17,6 @@ (assoc :tags []) (assoc :discoveries {})))) -(defn identities [contacts] - (->> (map second contacts) - (remove (fn [{:keys [dapp? pending]}] - (or pending dapp?))) - (map :whisper-identity))) - (defmethod nav/preload-data! :discover [db _] (-> db @@ -46,7 +40,7 @@ :hashtags (vec hashtags) :profile {:name name :profile-image photo-path}}}] - (doseq [id (identities contacts)] + (doseq [id (u/identities contacts)] (protocol/send-status! {:web3 web3 :message (assoc message :to id)})) @@ -80,7 +74,7 @@ (register-handler :request-discoveries (u/side-effect! (fn [{:keys [current-public-key web3 contacts]}] - (doseq [id (identities contacts)] + (doseq [id (u/identities contacts)] (when-not (protocol/message-pending? web3 :discoveries-request id) (protocol/send-discoveries-request! {:web3 web3 diff --git a/src/status_im/protocol/core.cljs b/src/status_im/protocol/core.cljs index 438affbddf..d8c1ac64d4 100644 --- a/src/status_im/protocol/core.cljs +++ b/src/status_im/protocol/core.cljs @@ -43,6 +43,7 @@ (def send-status! discoveries/send-status!) (def send-discoveries-request! discoveries/send-discoveries-request!) (def send-discoveries-response! discoveries/send-discoveries-response!) +(def update-keys! discoveries/update-keys!) (def message-pending? d/message-pending?) diff --git a/src/status_im/protocol/discoveries.cljs b/src/status_im/protocol/discoveries.cljs index f3a61cdfcc..0c0c5ecc1e 100644 --- a/src/status_im/protocol/discoveries.cljs +++ b/src/status_im/protocol/discoveries.cljs @@ -29,7 +29,7 @@ message {:requires-ack? false :type :online - :payload {:timestamp (u/timestamp)} + :payload {:content {:timestamp (u/timestamp)}} :topics [(make-discover-topic (:from message))]})] (d/add-pending-message! web3 message'))) @@ -105,6 +105,26 @@ (get-in message [:payload :profile])) (update :payload dissoc :profile)))) +(s/def ::public string?) +(s/def ::private string?) +(s/def ::keypair (s/keys :req-un [::public ::private])) +(s/def :update-keys/payload + (s/keys :req-un [::keypair])) +(s/def :update-keys/message + (s/merge :protocol/message (s/keys :req-un [:update-keys/payload]))) +(s/def :update-keys/options + (s/keys :req-un [:update-keys/message :options/web3])) + +(defn update-keys! + [{:keys [web3 message] :as options}] + {:pre [(valid? :update-keys/options options)]} + (let [message (-> message + (assoc :type :update-keys + :requires-ack? false + :topics [(make-discover-topic (:from message))]) + (assoc-in [:payload :timestamp] (u/timestamp)))] + (d/add-pending-message! web3 message))) + (s/def :status/payload (s/merge :message/payload (s/keys :req-un [::status]))) (s/def :status/message diff --git a/src/status_im/protocol/handlers.cljs b/src/status_im/protocol/handlers.cljs index feb0b987fb..d3cfe40fe5 100644 --- a/src/status_im/protocol/handlers.cljs +++ b/src/status_im/protocol/handlers.cljs @@ -114,6 +114,7 @@ :discoveries-request (dispatch [:discoveries-request-received message]) :discoveries-response (dispatch [:discoveries-response-received message]) :profile (dispatch [:contact-update-received message]) + :update-keys (dispatch [:update-keys-received message]) :online (dispatch [:contact-online-received message]) :pending (dispatch [:pending-message-upsert message]) :sent (let [{:keys [to id group-id]} message diff --git a/src/status_im/protocol/message.cljs b/src/status_im/protocol/message.cljs index 501b3be60d..93d7e2ca4a 100644 --- a/src/status_im/protocol/message.cljs +++ b/src/status_im/protocol/message.cljs @@ -22,7 +22,7 @@ #{:group-message :group-invitation :add-group-identity :remove-group-identity :leave-group :update-group}) -(s/def :discover-message/type #{:online :status :discover :contact-request}) +(s/def :discover-message/type #{:online :status :discover :contact-request :update-keys}) (s/def :message/type (s/or :group :group-message/type diff --git a/src/status_im/utils/handlers.cljs b/src/status_im/utils/handlers.cljs index db49a6609c..7b42a9ffcf 100644 --- a/src/status_im/utils/handlers.cljs +++ b/src/status_im/utils/handlers.cljs @@ -32,3 +32,9 @@ (re-seq #"#[^ !?,;:.]+" status))] (set (or hashtags []))) #{})) + +(defn identities [contacts] + (->> (map second contacts) + (remove (fn [{:keys [dapp? pending]}] + (or pending dapp?))) + (map :whisper-identity)))