migrate to new shh api

This commit is contained in:
Roman Volosovskyi 2017-05-12 16:27:05 +03:00 committed by Roman Volosovskyi
parent b94d1a51cb
commit 4655323fbb
20 changed files with 243 additions and 174 deletions

View File

@ -14,5 +14,5 @@ android {
dependencies {
compile 'com.facebook.react:react-native:+'
compile(group: 'status-im', name: 'status-go', version: '0.9.6-unstable-59-g1b31a5c', ext: 'aar')
compile(group: 'status-im', name: 'status-go', version: '0.9.8-g311f2b8', ext: 'aar')
}

View File

@ -25,7 +25,7 @@
<artifactItem>
<groupId>status-im</groupId>
<artifactId>status-go-ios-simulator</artifactId>
<version>0.9.6-unstable-59-g1b31a5c</version>
<version>0.9.8-g311f2b8</version>
<type>zip</type>
<overWrite>true</overWrite>
<outputDirectory>./</outputDirectory>

View File

@ -84,7 +84,7 @@
"tty-browserify": "0.0.0",
"url": "^0.10.3",
"vm-browserify": "0.0.4",
"web3": "github:status-im/web3.js#status-0.18.4"
"web3": "github:farazdagi/web3.js#geth/1.6.1-unstable"
},
"browser": {
"crypto": "react-native-crypto",

View File

@ -76,15 +76,16 @@
[{: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)]
(protocol/broadcast-profile!
{:web3 web3
:message {:from current-public-key
:message-id (random/id)
:keypair {:public updates-public-key
:private updates-private-key}
:payload {:profile {:name name
:status status
:profile-image photo-path}}}})))
(when web3
(protocol/broadcast-profile!
{:web3 web3
:message {:from current-public-key
:message-id (random/id)
:keypair {:public updates-public-key
:private updates-private-key}
:payload {:profile {:name name
:status status
:profile-image photo-path}}}}))))
(defn send-keys-update
[{:keys [current-account-id current-public-key web3 accounts contacts]} _]
@ -92,12 +93,12 @@
{: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}}}}))))
{: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
@ -118,20 +119,20 @@
(assoc-in db [:accounts current-account-id] account)))
(register-handler
:account-update
(-> (fn [db [_ data]]
(account-update db data))
((after save-account!))
((after broadcast-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))))
: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
@ -157,9 +158,9 @@
(map (fn [{:keys [address] :as account}]
[address account]))
(into {}))
view (if (empty? accounts)
:chat
:accounts)]
view (if (empty? accounts)
:chat
:accounts)]
(assoc db :accounts accounts
:view-id view
:navigation-stack (list view))))

View File

@ -4,11 +4,11 @@
(defn- get-id
[message-id to]
(let [to' (i/normalize-hex to)
(let [to' (i/normalize-hex to)
to'' (when to' (subs to' 0 7))
id' (if to''
(str message-id "-" (subs to'' 0 7))
message-id)]
id' (if to''
(str message-id "-" (subs to'' 0 7))
message-id)]
id'))
(defn get-all
@ -25,16 +25,18 @@
(defn save
[{:keys [id to group-id message] :as pending-message}]
(let [{:keys [from topics payload]} message
id' (get-id id to)
chat-id (or group-id to)
(let [{:keys [sig key type topic payload]} message
id' (get-id id to)
chat-id (or group-id to)
message' (-> pending-message
(assoc :id id'
:from from
:sig sig
:key key
:key-type type
:message-id id
:chat-id chat-id
:payload payload
:topics (prn-str topics))
:topic topic)
(dissoc :message))]
(data-store/save message')))

View File

@ -9,9 +9,7 @@
(defn get-all-as-list
[]
(->> (get-all)
realm/realm-collection->list
(map (fn [message]
(update message :topics read-string)))))
realm/realm-collection->list))
(defn get-by-message-id
[message-id]

View File

@ -16,7 +16,7 @@
:private-key {:type :string
:optional true}
:unremovable? {:type :bool
:default :false}
:default false}
:dapp? {:type :bool
:default false}
:dapp-url {:type :string

View File

@ -7,7 +7,7 @@
[status-im.data-store.realm.schemas.account.v1.discover :as discover]
[status-im.data-store.realm.schemas.account.v1.kv-store :as kv-store]
[status-im.data-store.realm.schemas.account.v4.message :as message]
[status-im.data-store.realm.schemas.account.v1.pending-message :as pending-message]
[status-im.data-store.realm.schemas.account.v7.pending-message :as pending-message]
[status-im.data-store.realm.schemas.account.v1.processed-message :as processed-message]
[status-im.data-store.realm.schemas.account.v1.request :as request]
[status-im.data-store.realm.schemas.account.v1.tag :as tag]

View File

@ -0,0 +1,27 @@
(ns status-im.data-store.realm.schemas.account.v7.pending-message
(:require [taoensso.timbre :as log]))
(def schema {:name :pending-message
:primaryKey :id
:properties {:id :string
:message-id :string
:chat-id {:type :string
:optional true}
:ack? :bool
:requires-ack? :bool
:sig :string
:key :string
:key-type :string
:to {:type :string
:optional true}
:payload :string
:type :string
:topic :string
:attempts :int
:was-sent? :bool}})
(defn migration [_ new-realm]
(log/debug "migrating pending-message schema v7")
(let [new-contacts (.objects new-realm "contact")]
(dotimes [i (.-length new-contacts)]
(.delete new-realm (aget new-contacts i)))))

View File

@ -6,9 +6,9 @@
[taoensso.timbre :refer-macros [debug]]
[status-im.protocol.validation :refer-macros [valid?]]
[status-im.protocol.web3.utils :as u]
[status-im.protocol.web3.keys :as shh-keys]
[status-im.protocol.chat :as chat]
[status-im.protocol.group :as group]
[status-im.protocol.web3.public-group :as public-group]
[status-im.protocol.listeners :as l]
[status-im.protocol.encryption :as e]
[status-im.protocol.discoveries :as discoveries]
@ -91,7 +91,7 @@
;; start listening to user's inbox
(f/add-filter!
web3
{:to identity
{:key identity
:topics [f/status-topic]}
(l/message-listener listener-options))
;; start listening to profiles

View File

@ -7,10 +7,11 @@
[status-im.protocol.listeners :as l]
[cljs.spec :as s]
[status-im.protocol.validation :refer-macros [valid?]]
[status-im.utils.random :as random]))
[status-im.utils.random :as random]
[status-im.protocol.web3.keys :as shh-keys]))
(def discover-topic-prefix "status-discover-")
(def discover-hashtag-prefix "status-hashtag-")
(def discover-topic "0xbeefdead")
(defn- make-discover-topic [identity]
(str discover-topic-prefix identity))
@ -21,6 +22,8 @@
(s/def :send-online/options
(s/keys :req-un [:options/web3 :send-online/message]))
(def discovery-key-password "status-discovery")
(defn send-online!
[{:keys [web3 message] :as options}]
{:pre [(valid? :send-online/options options)]}
@ -29,8 +32,9 @@
message
{:requires-ack? false
:type :online
:key-password discovery-key-password
:payload {:content {:timestamp (u/timestamp)}}
:topics [(make-discover-topic (:from message))]})]
:topics [f/status-topic]})]
(d/add-pending-message! web3 message')))
(s/def ::identity :message/from)
@ -40,18 +44,30 @@
(defn watch-user!
[{:keys [web3 identity] :as options}]
{:pre [(valid? :watch-user/options options)]}
(f/add-filter!
(shh-keys/get-sym-key
web3
{:from identity
:topics [(make-discover-topic identity)]}
(l/message-listener (dissoc options :identity))))
discovery-key-password
(fn [key-id]
(f/add-filter!
web3
{:sig identity
:topics [f/status-topic]
:key key-id
:type :sym}
(l/message-listener (dissoc options :identity))))))
(defn stop-watching-user!
[{:keys [web3 identity]}]
(f/remove-filter!
(shh-keys/get-sym-key
web3
{:from identity
:topics [(make-discover-topic identity)]}))
discovery-key-password
(fn [key-id]
(f/remove-filter!
web3
{:sig identity
:topics [f/status-topic]
:key key-id
:type :sym}))))
(s/def :contact-request/contact map?)
@ -99,7 +115,8 @@
web3
(-> message
(assoc :type :profile
:topics [(make-discover-topic (:from message))])
:topics [f/status-topic]
:key-password discovery-key-password)
(assoc-in [:payload :timestamp] (u/timestamp))
(assoc-in [:payload :content :profile]
(get-in message [:payload :profile]))
@ -121,7 +138,8 @@
(let [message (-> message
(assoc :type :update-keys
:requires-ack? false
:topics [(make-discover-topic (:from message))])
:key-password discovery-key-password
:topics [f/status-topic])
(assoc-in [:payload :timestamp] (u/timestamp)))]
(d/add-pending-message! web3 message)))
@ -136,7 +154,8 @@
[{:keys [web3 message]}]
(debug :broadcasting-status)
(let [message (assoc message :type :discover
:topics [(make-discover-topic (:from message))])]
:key-password discovery-key-password
:topics [f/status-topic])]
(d/add-pending-message! web3 message)))
(defn send-discoveries-request!
@ -145,7 +164,8 @@
(d/add-pending-message!
web3
(assoc message :type :discoveries-request
:topics [(make-discover-topic (:from message))])))
:key-password discovery-key-password
:topics [f/status-topic])))
(defn send-discoveries-response!
[{:keys [web3 discoveries message]}]
@ -156,6 +176,7 @@
(d/add-pending-message!
web3
(assoc message :type :discoveries-response
:topics [(make-discover-topic (:from message))]
:key-password discovery-key-password
:topics [f/status-topic]
:message-id (random/id)
:payload {:data (into [] portion)}))))

View File

@ -7,7 +7,8 @@
[status-im.protocol.validation :refer-macros [valid?]]
[status-im.protocol.web3.filtering :as f]
[status-im.protocol.listeners :as l]
[clojure.string :as str]))
[clojure.string :as str]
[status-im.protocol.web3.keys :as shh-keys]))
(defn prepare-mesage
[{:keys [message group-id keypair new-keypair type username requires-ack?]}]
@ -17,7 +18,8 @@
:group-id group-id
:type type
:timestamp (u/timestamp))
(assoc :topics [group-id]
(assoc :topics [f/status-topic]
:key-password group-id
:requires-ack? (or (nil? requires-ack?) requires-ack?)
:type type))]
(cond-> message'
@ -25,9 +27,10 @@
new-keypair (assoc :new-keypair keypair))))
(defn- send-group-message!
[{:keys [web3] :as opts} type]
[{:keys [web3 group-id] :as opts} type]
(let [message (-> opts
(assoc :type type)
(assoc :type type
:key-password group-id)
(prepare-mesage))]
(debug :send-group-message message)
(d/add-pending-message! web3 message)))
@ -116,14 +119,28 @@
(defn stop-watching-group!
[{:keys [web3 group-id]}]
{:pre [(valid? :message/chat-id group-id)]}
(f/remove-filter! web3 {:topics [group-id]}))
(shh-keys/get-sym-key
web3
group-id
(fn [key-id]
(f/remove-filter!
web3
{:topics [f/status-topic]
:key key-id
:type :sym}))))
(defn start-watching-group!
[{:keys [web3 group-id keypair callback identity]}]
(f/add-filter!
(shh-keys/get-sym-key
web3
{:topics [group-id]}
(l/message-listener {:web3 web3
:identity identity
:callback callback
:keypair keypair})))
group-id
(fn [key-id]
(f/add-filter!
web3
{:topics [f/status-topic]
:key key-id
:type :sym}
(l/message-listener {:web3 web3
:identity identity
:callback callback
:keypair keypair})))))

View File

@ -39,7 +39,7 @@
(debug :listener-error error))
(when-not error
(debug :message-received (js->clj js-message))
(let [{:keys [from payload to] :as message}
(let [{:keys [sig payload recipientPublicKey] :as message}
(js->clj js-message :keywordize-keys true)
{{:keys [type ack?] :as payload'} :payload
@ -47,18 +47,20 @@
(parse-payload payload)]
(when (and (not payload-error)
(or (not= (i/normalize-hex identity)
(i/normalize-hex from))
(i/normalize-hex sig))
;; allow user to receive his own discoveries
(= type :discover)))
(let [{:keys [content error]} (parse-content (:private keypair)
payload'
(and (not= "0x0" to)
(not= "" to)
(not (nil? to))))]
(and (not= "0x0" recipientPublicKey)
(not= "" recipientPublicKey)
(not (nil? recipientPublicKey))))]
(if error
(debug :failed-to-handle-message error)
(let [payload'' (assoc payload' :content content)
message' (assoc message :payload payload'')]
message' (assoc message :payload payload''
:to recipientPublicKey
:from sig)]
(callback (if ack? :ack type) message')
(ack/check-ack! web3 from payload'' identity)))))))))
(ack/check-ack! web3 sig payload'' identity)))))))))

View File

@ -3,6 +3,10 @@
(s/def :message/ttl (s/and int? pos?))
(s/def :message/from string?)
(s/def :message/sig :message/from)
(s/def :message/key string?)
(s/def :message/topic string?)
(s/def :message-key/type #{:sym :asym "sym" "asym"})
(s/def :message/to (s/nilable string?))
(s/def :message/message-id string?)
(s/def :message/requires-ack? boolean?)

View File

@ -7,17 +7,19 @@
[cljs.spec :as s]
[taoensso.timbre :refer-macros [debug] :as log]
[status-im.protocol.validation :refer-macros [valid?]]
[clojure.set :as set]))
[clojure.set :as set]
[status-im.protocol.web3.keys :as shh-keys]))
(defonce loop-state (atom nil))
(defonce messages (atom {}))
(defn prepare-message
[{:keys [payload keypair to] :as message}]
(debug :prepare-message!)
[web3 {:keys [payload keypair to from topics ttl key-password]
:as message}
callback]
(let [{:keys [public]} keypair
content (:content payload)
content (:content payload)
content' (if (and (not to) public content)
(e/encrypt public (prn-str content))
content)
@ -28,13 +30,22 @@
(assoc :content content')
prn-str
u/from-utf8)]
(-> message
(select-keys [:from :to :topics :ttl])
(assoc :payload payload'))))
(shh-keys/get-sym-key
web3
(or key-password shh-keys/status-key-password)
(fn [status-key-id]
(callback
(merge
(select-keys message [:ttl])
{:type (if to :asym :sym)
:sig from
:key (or to status-key-id)
:topic (first topics)
:payload payload'}))))))
(s/def :shh/pending-message
(s/keys :req-un [:message/from :shh/payload :message/topics]
:opt-un [:message/ttl :message/to]))
(s/keys :req-un [:message/sig :message-key/type :shh/payload :message/topic]
:opt-un [:message/ttl :message/key]))
(defonce pending-mesage-callback (atom nil))
(defonce recipient->pending-message (atom {}))
@ -47,37 +58,41 @@
[web3 {:keys [type message-id requires-ack? to ack?] :as message}]
{:pre [(valid? :protocol/message message)]}
(go
(debug :add-pending-message!)
(debug :add-pending-message! message)
;; encryption can take some time, better to run asynchronously
(let [message' (prepare-message message)]
(when (valid? :shh/pending-message message')
(let [group-id (get-in message [:payload :group-id])
pending-message {:id message-id
:ack? (boolean ack?)
:message message'
:to to
:type type
:group-id group-id
:requires-ack? (boolean requires-ack?)
:attempts 0
:was-sent? false}]
(when (and @pending-mesage-callback requires-ack?)
(@pending-mesage-callback :pending pending-message))
(swap! messages assoc-in [web3 message-id to] pending-message)
(when to
(swap! recipient->pending-message
update to set/union #{[web3 message-id to]})))))))
(prepare-message
web3 message
(fn [message']
(when (valid? :shh/pending-message message')
(let [group-id (get-in message [:payload :group-id])
pending-message {:id message-id
:ack? (boolean ack?)
:message message'
:to to
:type type
:group-id group-id
:requires-ack? (boolean requires-ack?)
:attempts 0
:was-sent? false}]
(when (and @pending-mesage-callback requires-ack?)
(@pending-mesage-callback :pending pending-message))
(swap! messages assoc-in [web3 message-id to] pending-message)
(when to
(swap! recipient->pending-message
update to set/union #{[web3 message-id to]}))))))))
(s/def :delivery/pending-message
(s/keys :req-un [:message/from :message/to :shh/payload
:message/requires-ack? :payload/ack? ::id :message/topics
(s/keys :req-un [:message/sig :message/key :message/to :shh/payload
:message/requires-ack? :payload/ack? ::id :message/topic
::attempts ::was-sent?]))
(defn add-prepeared-pending-message!
[web3 {:keys [message-id to] :as pending-message}]
[web3 {:keys [message-id to key-type] :as pending-message}]
{:pre [(valid? :delivery/pending-message pending-message)]}
(debug :add-prepeared-pending-message!)
(let [message (select-keys pending-message [:from :to :topics :payload])
(let [message (-> pending-message
(select-keys [:sig :key :topics :payload])
(assoc :type key-type))
pending-message' (assoc pending-message :message message
:id message-id)]
(swap! messages assoc-in [web3 message-id to] pending-message')
@ -89,7 +104,7 @@
(swap! messages update web3
(fn [messages]
(when messages
(let [message (messages id)
(let [message (messages id)
;; Message that is send without specified "from" option
;; is stored in pending "messages" map as
;; {message-id {nil message}}.
@ -108,7 +123,7 @@
(defn message-was-sent! [web3 id to]
(let [messages' (swap! messages update web3
(fn [messages]
(let [message (get-in messages [id to])
(let [message (get-in messages [id to])
message' (when message
(assoc message :was-sent? true
:attempts 1))]
@ -191,7 +206,7 @@
{:pre [(valid? ::delivery-options options)]}
(debug :run-delivery-loop!)
(let [previous-stop-flag @loop-state
stop? (atom false)]
stop? (atom false)]
;; stop previous delivery loop if it exists
(when previous-stop-flag
(reset! previous-stop-flag true))

View File

@ -3,7 +3,7 @@
[cljs.spec :as s]
[taoensso.timbre :as log]))
(def status-topic "status-dapp-topic")
(def status-topic "0xaabb11ee")
(defonce filters (atom {}))
(s/def ::options (s/keys :opt-un [:message/to :message/topics]))
@ -19,36 +19,17 @@
(defn add-shh-filter!
[web3 options callback]
(fn do-add-filter-fn
([] (do-add-filter-fn nil))
([keyname]
(let [options' (if keyname
(assoc options :keyname keyname)
options)
filter (.filter (u/shh web3) (clj->js options')
callback
#(log/warn :add-filter-error options %))]
(swap! filters assoc-in [web3 options] filter)))))
(let [options' (update options :type (fn [t] (or t :asym)))
filter (.filter (u/shh web3) (clj->js options')
callback
#(log/warn :add-filter-error options %))]
(swap! filters assoc-in [web3 options] filter)))
(defn add-filter!
[web3 {:keys [topics to] :as options} callback]
(remove-filter! web3 options)
(log/debug :add-filter options)
(let [shh (u/shh web3)
encrypted? (boolean to)
do-add-filter (add-shh-filter! web3 options callback)]
(if encrypted?
(do-add-filter)
(let [topic (first topics)]
(.hasSymKey
shh topic
(fn [error res]
(if-not res
(.addSymKey
shh topic u/status-key-data
(fn [error res]
(when-not error (do-add-filter topic))))
(do-add-filter topic))))))))
(add-shh-filter! web3 options callback))
(defn remove-all-filters! []
(doseq [[web3 filters] @filters]

View File

@ -0,0 +1,27 @@
(ns status-im.protocol.web3.keys)
(defonce status-sym-key-id (atom nil))
(def status-key-password "status-key-password")
(def status-group-key-password "status-public-group-key-password")
(defonce password->keys (atom {}))
(defn- add-sym-key-from-password
[web3 password callback]
(.. web3
-shh
(addSymmetricKeyFromPassword password callback)))
(defn get-sym-key [web3 password callback]
(if-let [key-id (get @password->keys password)]
(callback key-id)
(add-sym-key-from-password
web3 password
(fn [err res]
(swap! password->keys assoc password res)
(callback res)))))
(defn get-status-sym-key
[web3 callback]
(get-sym-key web3 status-key-password callback))

View File

@ -1,7 +0,0 @@
(ns status-im.protocol.web3.public-group
(:require [status-im.protocol.web3.filtering :as f]
[status-im.protocol.listeners :as l]
[status-im.protocol.validation :refer-macros [valid?]]
[status-im.protocol.web3.delivery :as d]
[cljs.spec :as s]))

View File

@ -7,28 +7,12 @@
(s/def :shh/payload string?)
(s/def :shh/message
(s/keys
:req-un [:shh/payload :message/ttl :message/from :message/topics]
:opt-un [:message/to]))
:req-un [:shh/payload :message/ttl :message/key :message/sig
:message/topic :message-key/type]))
(defn post-message!
[web3 {:keys [topics from to] :as message} callback]
[web3 message callback]
{:pre [(valid? :shh/message message)]}
(debug :post-message message)
(let [topic (first topics)
shh (u/shh web3)
encrypted? (boolean to)
message' (if encrypted?
message
(assoc message :keyname topic))
do-post (fn [] (.post shh (clj->js message') callback))]
(if encrypted?
(do-post)
(.hasSymKey
shh topic
(fn [_ res]
(if-not res
(.addSymKey
shh topic u/status-key-data
(fn [error _]
(when-not error (do-post))))
(do-post)))))))
(let [shh (u/shh web3)]
(.post shh (clj->js message) callback)))

View File

@ -24,6 +24,3 @@
(defn timestamp []
(to-long (now)))
(def status-key-data (.toHex web3.prototype "status-key-data"))