fix(wallet/accounts): don't store derived account when it exists in app db

As discussed in #10326 and later in https://github.com/status-im/status-go/issues/1939, it turns out
that, when a user tries to add an account (from a seed phrase), while an account
with the same address (that the seed phrase would result in) exists in the application
state, the application would still go ahead and store the derived account in
status-go.

After that it still reports to the user that the 'Account already exits'.

This commit ensures that Status doesn't try to store the derived account when
the account already exists in the application database.

Fixes #10326

Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
Pascal Precht 2020-04-22 14:57:38 +02:00 committed by Andrey Shovkoplyas
parent e1eda363e6
commit 3fce002213
No known key found for this signature in database
GPG Key ID: EAAB7C8622D860A4

View File

@ -59,7 +59,7 @@
"/" (last (string/split path "/"))) "/" (last (string/split path "/")))
path)) path))
(defn derive-and-store-account [path hashed-password type] (defn derive-and-store-account [path hashed-password type accounts]
(fn [value] (fn [value]
(let [{:keys [id error]} (types/json->clj value)] (let [{:keys [id error]} (types/json->clj value)]
(if error (if error
@ -67,22 +67,25 @@
(status/multiaccount-derive-addresses (status/multiaccount-derive-addresses
id id
[path] [path]
(fn [_] (fn [derived]
(status/multiaccount-store-derived (let [derived-address (get-in (types/json->clj derived) [(keyword path) :address])]
id (if (some #(= derived-address (get % :address)) accounts)
[path] (re-frame/dispatch [::new-account-error :account-error (i18n/label :t/account-exists-title)])
hashed-password (status/multiaccount-store-derived
(fn [result] id
(let [{:keys [error] :as result} (types/json->clj result) [path]
{:keys [publicKey address]} (get result (keyword path))] hashed-password
(if error (fn [result]
(re-frame/dispatch [::new-account-error :account-error error]) (let [{:keys [error] :as result} (types/json->clj result)
(re-frame/dispatch {:keys [publicKey address]} (get result (keyword path))]
[:wallet.accounts/account-stored (if error
{:address address (re-frame/dispatch [::new-account-error :account-error error])
:public-key publicKey (re-frame/dispatch
:type type [:wallet.accounts/account-stored
:path (normalize-path path)}]))))))))))) {:address address
:public-key publicKey
:type type
:path (normalize-path path)}])))))))))))))
(def pass-error "cannot retrieve a valid key for a given account: could not decrypt key with given password") (def pass-error "cannot retrieve a valid key for a given account: could not decrypt key with given password")
@ -107,20 +110,20 @@
(re-frame/reg-fx (re-frame/reg-fx
::generate-account ::generate-account
(fn [{:keys [derivation-info hashed-password]}] (fn [{:keys [derivation-info hashed-password accounts]}]
(let [{:keys [address path]} derivation-info] (let [{:keys [address path]} derivation-info]
(status/multiaccount-load-account (status/multiaccount-load-account
address address
hashed-password hashed-password
(derive-and-store-account path hashed-password :generated))))) (derive-and-store-account path hashed-password :generated accounts)))))
(re-frame/reg-fx (re-frame/reg-fx
::import-account-seed ::import-account-seed
(fn [{:keys [passphrase hashed-password]}] (fn [{:keys [passphrase hashed-password accounts]}]
(status/multiaccount-import-mnemonic (status/multiaccount-import-mnemonic
(mnemonic/sanitize-passphrase (security/unmask passphrase)) (mnemonic/sanitize-passphrase (security/unmask passphrase))
"" ""
(derive-and-store-account constants/path-default-wallet hashed-password :seed)))) (derive-and-store-account constants/path-default-wallet hashed-password :seed accounts))))
(re-frame/reg-fx (re-frame/reg-fx
::import-account-private-key ::import-account-private-key
@ -132,7 +135,8 @@
(fx/defn generate-new-account (fx/defn generate-new-account
[{:keys [db]} hashed-password] [{:keys [db]} hashed-password]
(let [wallet-root-address (get-in db [:multiaccount :wallet-root-address]) (let [wallet-root-address (get-in db [:multiaccount :wallet-root-address])
path-num (inc (get-in db [:multiaccount :latest-derived-path]))] path-num (inc (get-in db [:multiaccount :latest-derived-path]))
accounts (:multiaccount/accounts db)]
{:db (assoc-in db [:add-account :step] :generating) {:db (assoc-in db [:add-account :step] :generating)
::generate-account {:derivation-info (if wallet-root-address ::generate-account {:derivation-info (if wallet-root-address
;; Use the walllet-root-address for stored on disk keys ;; Use the walllet-root-address for stored on disk keys
@ -142,7 +146,8 @@
;; Fallback on the master account for keycards, use the absolute path ;; Fallback on the master account for keycards, use the absolute path
{:path (str constants/path-wallet-root "/" path-num) {:path (str constants/path-wallet-root "/" path-num)
:address (get-in db [:multiaccount :address])}) :address (get-in db [:multiaccount :address])})
:hashed-password hashed-password}})) :hashed-password hashed-password
:accounts accounts}}))
(fx/defn import-new-account-seed (fx/defn import-new-account-seed
[{:keys [db]} passphrase hashed-password] [{:keys [db]} passphrase hashed-password]
@ -157,8 +162,11 @@
(let [error (:error (types/json->clj phrase-warnings))] (let [error (:error (types/json->clj phrase-warnings))]
(if-not (string/blank? error) (if-not (string/blank? error)
(new-account-error cofx :account-error error) (new-account-error cofx :account-error error)
{::import-account-seed {:passphrase passphrase (let [{:keys [db]} cofx
:hashed-password hashed-password}}))) accounts (:multiaccount/accounts db)]
{::import-account-seed {:passphrase passphrase
:hashed-password hashed-password
:accounts accounts}}))))
(fx/defn import-new-account-private-key (fx/defn import-new-account-private-key
[{:keys [db]} private-key hashed-password] [{:keys [db]} private-key hashed-password]