diff --git a/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java b/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java index 94a27f9206e..78e9ad3c82f 100644 --- a/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java +++ b/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java @@ -246,7 +246,7 @@ private String pathCombine(final String path1, final String path2) { return file.getAbsolutePath(); } - private String prepareDirAndUpdateConfig(final String jsonConfigString) { + private String prepareDirAndUpdateConfig(final String jsonConfigString, final String keyUID) { Activity currentActivity = getCurrentActivity(); @@ -303,7 +303,8 @@ private String prepareDirAndUpdateConfig(final String jsonConfigString) { } try { - final String updatedJsonConfigString = this.updateConfig(jsonConfigString, absRootDirPath, "/keystore"); + final String multiaccountKeystoreDir = pathCombine("/keystore", keyUID); + final String updatedJsonConfigString = this.updateConfig(jsonConfigString, absRootDirPath, multiaccountKeystoreDir); prettyPrintConfig(updatedJsonConfigString); @@ -317,41 +318,55 @@ private String prepareDirAndUpdateConfig(final String jsonConfigString) { } @ReactMethod - public void prepareDirAndUpdateConfig(final String config, final Callback callback) { + public void prepareDirAndUpdateConfig(final String keyUID, final String config, final Callback callback) { Log.d(TAG, "prepareDirAndUpdateConfig"); - String finalConfig = prepareDirAndUpdateConfig(config); + String finalConfig = prepareDirAndUpdateConfig(config, keyUID); callback.invoke(finalConfig); } @ReactMethod public void saveAccountAndLogin(final String multiaccountData, final String password, final String settings, final String config, final String accountsData) { - Log.d(TAG, "saveAccountAndLogin"); - String finalConfig = prepareDirAndUpdateConfig(config); - String result = Statusgo.saveAccountAndLogin(multiaccountData, password, settings, finalConfig, accountsData); - if (result.startsWith("{\"error\":\"\"")) { - Log.d(TAG, "saveAccountAndLogin result: " + result); - Log.d(TAG, "Geth node started"); - } else { - Log.e(TAG, "saveAccountAndLogin failed: " + result); + try { + Log.d(TAG, "saveAccountAndLogin"); + String finalConfig = prepareDirAndUpdateConfig(config, this.getKeyUID(multiaccountData)); + String result = Statusgo.saveAccountAndLogin(multiaccountData, password, settings, finalConfig, accountsData); + if (result.startsWith("{\"error\":\"\"")) { + Log.d(TAG, "saveAccountAndLogin result: " + result); + Log.d(TAG, "Geth node started"); + } else { + Log.e(TAG, "saveAccountAndLogin failed: " + result); + } + } catch (JSONException e) { + Log.e(TAG, "JSON conversion failed: " + e.getMessage()); } } @ReactMethod public void saveAccountAndLoginWithKeycard(final String multiaccountData, final String password, final String settings, final String config, final String accountsData, final String chatKey) { - Log.d(TAG, "saveAccountAndLoginWithKeycard"); - String finalConfig = prepareDirAndUpdateConfig(config); - String result = Statusgo.saveAccountAndLoginWithKeycard(multiaccountData, password, settings, finalConfig, accountsData, chatKey); - if (result.startsWith("{\"error\":\"\"")) { - Log.d(TAG, "saveAccountAndLoginWithKeycard result: " + result); - Log.d(TAG, "Geth node started"); - } else { - Log.e(TAG, "saveAccountAndLoginWithKeycard failed: " + result); + try { + Log.d(TAG, "saveAccountAndLoginWithKeycard"); + String finalConfig = prepareDirAndUpdateConfig(config, this.getKeyUID(multiaccountData)); + String result = Statusgo.saveAccountAndLoginWithKeycard(multiaccountData, password, settings, finalConfig, accountsData, chatKey); + if (result.startsWith("{\"error\":\"\"")) { + Log.d(TAG, "saveAccountAndLoginWithKeycard result: " + result); + Log.d(TAG, "Geth node started"); + } else { + Log.e(TAG, "saveAccountAndLoginWithKeycard failed: " + result); + } + } catch (JSONException e) { + Log.e(TAG, "JSON conversion failed: " + e.getMessage()); } } + private String getKeyUID(final String json) throws JSONException { + final JSONObject jsonObj = new JSONObject(json); + return jsonObj.getString("key-uid"); + } + @ReactMethod public void login(final String accountData, final String password) { Log.d(TAG, "login"); + this.migrateKeyStoreDir(accountData, password); String result = Statusgo.login(accountData, password); if (result.startsWith("{\"error\":\"\"")) { Log.d(TAG, "Login result: " + result); @@ -416,23 +431,25 @@ private void copyDirectory(File sourceLocation, File targetLocation) throws IOEx } @ReactMethod - private void initKeystore() { + private void initKeystore(final String keyUID, final Callback callback) { Log.d(TAG, "initKeystore"); Activity currentActivity = getCurrentActivity(); - final String keydir = pathCombine(this.getNoBackupDirectory(), "/keystore"); - if (!checkAvailability()) { Log.e(TAG, "[initKeystore] Activity doesn't exist, cannot init keystore"); System.exit(0); return; } + final String commonKeydir = pathCombine(this.getNoBackupDirectory(), "/keystore"); + final String keydir = pathCombine(commonKeydir, keyUID); + Runnable r = new Runnable() { @Override public void run() { Statusgo.initKeystore(keydir); + callback.invoke(true); } }; @@ -487,9 +504,27 @@ public void run() { StatusThreadPoolExecutor.getInstance().execute(r); } + public void migrateKeyStoreDir(final String accountData, final String password) { + try { + final String commonKeydir = pathCombine(this.getNoBackupDirectory(), "/keystore"); + final String keydir = pathCombine(commonKeydir, getKeyUID(accountData)); + Log.d(TAG, "before migrateKeyStoreDir " + keydir); + + File keydirFile = new File(keydir); + if(!keydirFile.exists() || keydirFile.list().length == 0) { + Log.d(TAG, "migrateKeyStoreDir"); + Statusgo.migrateKeyStoreDir(accountData, password, commonKeydir, keydir); + Statusgo.initKeystore(keydir); + } + } catch (JSONException e) { + Log.e(TAG, "JSON conversion failed: " + e.getMessage()); + } + } + @ReactMethod public void loginWithKeycard(final String accountData, final String password, final String chatKey) { Log.d(TAG, "loginWithKeycard"); + this.migrateKeyStoreDir(accountData, password); String result = Statusgo.loginWithKeycard(accountData, password, chatKey); if (result.startsWith("{\"error\":\"\"")) { Log.d(TAG, "LoginWithKeycard result: " + result); diff --git a/modules/react-native-status/ios/RCTStatus/RCTStatus.m b/modules/react-native-status/ios/RCTStatus/RCTStatus.m index 39e4015ebb8..c9299e69ac6 100644 --- a/modules/react-native-status/ios/RCTStatus/RCTStatus.m +++ b/modules/react-native-status/ios/RCTStatus/RCTStatus.m @@ -110,7 +110,8 @@ - (void)handleSignal:(NSString *)signal //////////////////////////////////////////////////////////////////// #pragma mark - InitKeystore method //////////////////////////////////////////////////////////////////// StopNode -RCT_EXPORT_METHOD(initKeystore) { +RCT_EXPORT_METHOD(initKeystore:(NSString *)keyUID + callback:(RCTResponseSenderBlock)callback) { #if DEBUG NSLog(@"initKeystore() method called"); #endif @@ -119,12 +120,15 @@ - (void)handleSignal:(NSString *)signal URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject]; - NSURL *keystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"]; + NSURL *commonKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"]; + NSURL *keystoreDir = [commonKeystoreDir URLByAppendingPathComponent:keyUID]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { NSString *res = StatusgoInitKeystore(keystoreDir.path); NSLog(@"InitKeyStore result %@", res); + callback(@[]); }); } @@ -306,8 +310,19 @@ - (void)handleSignal:(NSString *)signal callback(@[result]); } +-(NSString *) getKeyUID:(NSString *)jsonString { + NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary *json = [NSJSONSerialization + JSONObjectWithData:data + options:NSJSONReadingMutableContainers + error:nil]; + + return [json valueForKey:@"key-uid"]; +} + //////////////////////////////////////////////////////////////////// prepareDirAndUpdateConfig --(NSString *) prepareDirAndUpdateConfig:(NSString *)config { +-(NSString *) prepareDirAndUpdateConfig:(NSString *)config + withKeyUID:(NSString *)keyUID { NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error = nil; NSURL *rootUrl =[[fileManager @@ -354,7 +369,8 @@ -(NSString *) prepareDirAndUpdateConfig:(NSString *)config { NSURL *absDataDirUrl = [NSURL fileURLWithPath:absDataDir]; NSURL *dataDirUrl = [NSURL fileURLWithPath:relativeDataDir]; NSURL *logUrl = [dataDirUrl URLByAppendingPathComponent:@"geth.log"]; - [configJSON setValue:@"/keystore" forKey:@"KeyStoreDir"]; + NSString *keystoreDir = [@"/keystore/" stringByAppendingString:keyUID]; + [configJSON setValue:keystoreDir forKey:@"KeyStoreDir"]; [configJSON setValue:@"" forKey:@"LogDir"]; [configJSON setValue:logUrl.path forKey:@"LogFile"]; @@ -380,15 +396,15 @@ -(NSString *) prepareDirAndUpdateConfig:(NSString *)config { //////////////////////////////////////////////////////////////////// prepareDirAndUpdateConfig -RCT_EXPORT_METHOD(prepareDirAndUpdateConfig:(NSString *)config +RCT_EXPORT_METHOD(prepareDirAndUpdateConfig:(NSString *)keyUID + config:(NSString *)config callback:(RCTResponseSenderBlock)callback) { - #if DEBUG NSLog(@"PrepareDirAndUpdateConfig() method called"); #endif - NSString *updatedConfig = [self prepareDirAndUpdateConfig:config]; + NSString *updatedConfig = [self prepareDirAndUpdateConfig:config + withKeyUID:keyUID]; callback(@[updatedConfig]); - } //////////////////////////////////////////////////////////////////// saveAccountAndLogin @@ -400,7 +416,9 @@ -(NSString *) prepareDirAndUpdateConfig:(NSString *)config { #if DEBUG NSLog(@"SaveAccountAndLogin() method called"); #endif - NSString *finalConfig = [self prepareDirAndUpdateConfig:config]; + NSString *keyUID = [self getKeyUID:multiaccountData]; + NSString *finalConfig = [self prepareDirAndUpdateConfig:config + withKeyUID:keyUID]; NSString *result = StatusgoSaveAccountAndLogin(multiaccountData, password, settings, finalConfig, accountsData); NSLog(@"%@", result); } @@ -415,17 +433,41 @@ -(NSString *) prepareDirAndUpdateConfig:(NSString *)config { #if DEBUG NSLog(@"SaveAccountAndLoginWithKeycard() method called"); #endif - NSString *finalConfig = [self prepareDirAndUpdateConfig:config]; + NSString *keyUID = [self getKeyUID:multiaccountData]; + NSString *finalConfig = [self prepareDirAndUpdateConfig:config + withKeyUID:keyUID]; NSString *result = StatusgoSaveAccountAndLoginWithKeycard(multiaccountData, password, settings, finalConfig, accountsData, chatKey); NSLog(@"%@", result); } +- (void) migrateKeystore:(NSString *)accountData + password:(NSString *)password { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSURL *rootUrl =[[fileManager + URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] + lastObject]; + + NSString *keyUID = [self getKeyUID:accountData]; + NSURL *oldKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"]; + NSURL *multiaccountKeystoreDir = [oldKeystoreDir URLByAppendingPathComponent:keyUID]; + + NSArray *keys = [fileManager contentsOfDirectoryAtPath:multiaccountKeystoreDir.path error:nil]; + if (keys.count == 0) { + NSString *migrationResult = StatusgoMigrateKeyStoreDir(accountData, password, oldKeystoreDir.path, multiaccountKeystoreDir.path); + NSLog(@"keystore migration result %@", migrationResult); + + NSString *initKeystoreResult = StatusgoInitKeystore(multiaccountKeystoreDir.path); + NSLog(@"InitKeyStore result %@", initKeystoreResult); + } +} + //////////////////////////////////////////////////////////////////// login RCT_EXPORT_METHOD(login:(NSString *)accountData password:(NSString *)password) { #if DEBUG NSLog(@"Login() method called"); #endif + [self migrateKeystore:accountData password:password]; NSString *result = StatusgoLogin(accountData, password); NSLog(@"%@", result); } @@ -437,6 +479,8 @@ -(NSString *) prepareDirAndUpdateConfig:(NSString *)config { #if DEBUG NSLog(@"LoginWithKeycard() method called"); #endif + [self migrateKeystore:accountData password:password]; + NSString *result = StatusgoLoginWithKeycard(accountData, password, chatKey); NSLog(@"%@", result); diff --git a/src/status_im/hardwallet/common.cljs b/src/status_im/hardwallet/common.cljs index b1d136717ff..a4be4d02610 100644 --- a/src/status_im/hardwallet/common.cljs +++ b/src/status_im/hardwallet/common.cljs @@ -334,7 +334,8 @@ :hardwallet/get-application-info {:pairing (get-pairing db key-uid)} :hardwallet/login-with-keycard {:multiaccount-data multiaccount-data :password encryption-public-key - :chat-key whisper-private-key}} + :chat-key whisper-private-key + :key-uid key-uid}} (when save-keys? (keychain/save-hardwallet-keys key-uid encryption-public-key whisper-private-key)) (clear-on-card-connected) diff --git a/src/status_im/hardwallet/real_keycard.cljs b/src/status_im/hardwallet/real_keycard.cljs index 9d5ff2d6d26..ee64d72a214 100644 --- a/src/status_im/hardwallet/real_keycard.cljs +++ b/src/status_im/hardwallet/real_keycard.cljs @@ -213,8 +213,9 @@ (catch on-failure)))) (defn save-multiaccount-and-login - [{:keys [multiaccount-data password settings node-config accounts-data chat-key]}] + [{:keys [key-uid multiaccount-data password settings node-config accounts-data chat-key]}] (status/save-multiaccount-and-login-with-keycard + key-uid (types/clj->json multiaccount-data) password (types/clj->json settings) diff --git a/src/status_im/hardwallet/simulated_keycard.cljs b/src/status_im/hardwallet/simulated_keycard.cljs index bea944809fe..a76c3ff8d08 100644 --- a/src/status_im/hardwallet/simulated_keycard.cljs +++ b/src/status_im/hardwallet/simulated_keycard.cljs @@ -143,6 +143,7 @@ (log/debug "[simulated kk] generate-and-load-key response" response) (status/multiaccount-store-derived id + key-uid [constants/path-wallet-root constants/path-eip1581 constants/path-whisper @@ -197,9 +198,8 @@ path)) (defn export-key [{:keys [pin on-success on-failure]}] - (let [wallet-root-address (get-in - @re-frame.db/app-db - [:multiaccount :wallet-root-address]) + (let [{:keys [key-uid wallet-root-address]} + (get @re-frame.db/app-db :multiaccount) accounts (get @re-frame.db/app-db :multiaccount/accounts) hashed-password (ethereum/sha3 pin) path-num (inc (get-in @re-frame.db/app-db [:multiaccount :latest-derived-path])) @@ -220,6 +220,7 @@ (re-frame/dispatch [::new-account-error :account-error (i18n/label :t/account-exists-title)]) (status/multiaccount-store-derived id + key-uid [path] hashed-password (fn [result] @@ -293,16 +294,17 @@ (log/warn "sign-typed-data not implemented" args)) (defn save-multiaccount-and-login - [{:keys [multiaccount-data password settings node-config accounts-data]}] + [{:keys [key-uid multiaccount-data password settings node-config accounts-data]}] (status/save-account-and-login + key-uid (types/clj->json multiaccount-data) password (types/clj->json settings) node-config (types/clj->json accounts-data))) -(defn login [{:keys [multiaccount-data password]}] - (status/login multiaccount-data password)) +(defn login [{:keys [key-uid multiaccount-data password]}] + (status/login key-uid multiaccount-data password)) (defn send-transaction-with-signature [{:keys [transaction on-completed]}] diff --git a/src/status_im/init/core.cljs b/src/status_im/init/core.cljs index e9a5538d240..3a6cd7f4310 100644 --- a/src/status_im/init/core.cljs +++ b/src/status_im/init/core.cljs @@ -55,7 +55,6 @@ (fx/merge cofx {:get-supported-biometric-auth nil ::init-theme nil - ::init-keystore nil ::open-multiaccounts #(re-frame/dispatch [::initialize-multiaccounts % {:logout? false}]) :ui/listen-to-window-dimensions-change nil ::network/listen-to-network-info nil @@ -70,11 +69,6 @@ (fn [callback] (status/open-accounts callback))) -(re-frame/reg-fx - ::init-keystore - (fn [] - (status/init-keystore))) - (re-frame/reg-fx ::init-theme (fn [] diff --git a/src/status_im/multiaccounts/create/core.cljs b/src/status_im/multiaccounts/create/core.cljs index ce0cf3c042d..9053d2ea6d6 100644 --- a/src/status_im/multiaccounts/create/core.cljs +++ b/src/status_im/multiaccounts/create/core.cljs @@ -71,6 +71,11 @@ (fx/defn create-multiaccount [{:keys [db]}] (let [{:keys [selected-id key-code]} (:intro-wizard db) + key-uid (some + (fn [{:keys [id key-uid]}] + (when (= id selected-id) + key-uid)) + (get-in db [:intro-wizard :multiaccounts])) hashed-password (ethereum/sha3 (security/safe-unmask-data key-code)) callback (fn [result] (let [derived-data (normalize-derived-data-keys (types/json->clj result)) @@ -84,7 +89,7 @@ (merge derived-whisper {:name name :photo-path photo-path}))] (re-frame/dispatch [::store-multiaccount-success key-code derived-data-extended]))))))] - {::store-multiaccount [selected-id hashed-password callback]})) + {::store-multiaccount [selected-id key-uid hashed-password callback]})) (fx/defn prepare-intro-wizard [{:keys [db] :as cofx}] @@ -230,8 +235,9 @@ {:hardwallet/save-multiaccount-and-login args}) (fx/defn save-account-and-login - [_ multiaccount-data password settings node-config accounts-data] - {::save-account-and-login [(types/clj->json multiaccount-data) + [_ key-uid multiaccount-data password settings node-config accounts-data] + {::save-account-and-login [key-uid + (types/clj->json multiaccount-data) password (types/clj->json settings) node-config @@ -303,17 +309,20 @@ {:db db} (if keycard-multiaccount? (save-multiaccount-and-login-with-keycard - {:multiaccount-data multiaccount-data + {:key-uid key-uid + :multiaccount-data multiaccount-data :password password :settings settings :node-config (node/get-new-config db) :accounts-data accounts-data :chat-key chat-key}) - (save-account-and-login multiaccount-data - (ethereum/sha3 (security/safe-unmask-data password)) - settings - (node/get-new-config db) - accounts-data)) + (save-account-and-login + key-uid + multiaccount-data + (ethereum/sha3 (security/safe-unmask-data password)) + settings + (node/get-new-config db) + accounts-data)) (when (:intro-wizard db) (intro-step-forward {}))))) @@ -401,9 +410,10 @@ (re-frame/reg-fx ::store-multiaccount - (fn [[id hashed-password callback]] + (fn [[id key-uid hashed-password callback]] (status/multiaccount-store-derived id + key-uid [constants/path-wallet-root constants/path-eip1581 constants/path-whisper @@ -413,9 +423,11 @@ (re-frame/reg-fx ::save-account-and-login - (fn [[multiaccount-data hashed-password settings config accounts-data]] - (status/save-account-and-login multiaccount-data - hashed-password - settings - config - accounts-data))) + (fn [[key-uid multiaccount-data hashed-password settings config accounts-data]] + (status/save-account-and-login + key-uid + multiaccount-data + hashed-password + settings + config + accounts-data))) diff --git a/src/status_im/multiaccounts/login/core.cljs b/src/status_im/multiaccounts/login/core.cljs index c3166f19bd4..b48528d5ab3 100644 --- a/src/status_im/multiaccounts/login/core.cljs +++ b/src/status_im/multiaccounts/login/core.cljs @@ -32,8 +32,8 @@ (re-frame/reg-fx ::login - (fn [[account-data hashed-password]] - (status/login account-data hashed-password))) + (fn [[key-uid account-data hashed-password]] + (status/login key-uid account-data hashed-password))) (defn rpc->accounts [accounts] (reduce (fn [acc {:keys [chat type wallet] :as account}] @@ -71,7 +71,8 @@ (assoc-in [:multiaccounts/login :processing] true) (dissoc :intro-wizard) (update :hardwallet dissoc :flow)) - ::login [(types/clj->json {:name name + ::login [key-uid + (types/clj->json {:name name :key-uid key-uid :photo-path photo-path}) (ethereum/sha3 (security/safe-unmask-data password))]})) diff --git a/src/status_im/multiaccounts/login/flow_test.cljs b/src/status_im/multiaccounts/login/flow_test.cljs index 6405c75c941..c4db11a9ff0 100644 --- a/src/status_im/multiaccounts/login/flow_test.cljs +++ b/src/status_im/multiaccounts/login/flow_test.cljs @@ -18,7 +18,7 @@ efx (login.core/login cofx)] (testing "Change multiaccount." (is (= (::login.core/login efx) - ["{\"name\":\"user\",\"key-uid\":\"key-uid\",\"photo-path\":\"photo\"}" (ethereum/sha3 "password")]))) + ["key-uid" "{\"name\":\"user\",\"key-uid\":\"key-uid\",\"photo-path\":\"photo\"}" (ethereum/sha3 "password")]))) (testing "start activity indicator" (is (= (get-in efx [:db :multiaccounts/login :processing]) true)))))) diff --git a/src/status_im/multiaccounts/recover/core.cljs b/src/status_im/multiaccounts/recover/core.cljs index 3e5975fc396..bab6e1f2f97 100644 --- a/src/status_im/multiaccounts/recover/core.cljs +++ b/src/status_im/multiaccounts/recover/core.cljs @@ -80,11 +80,11 @@ [{:keys [db]}] (let [password (get-in db [:intro-wizard :key-code]) {:keys [root-key]} (:intro-wizard db) - {:keys [id]} root-key + {:keys [id key-uid]} root-key callback #(re-frame/dispatch [::store-multiaccount-success % password]) hashed-password (ethereum/sha3 (security/safe-unmask-data password))] {:db (assoc-in db [:intro-wizard :processing?] true) - ::multiaccounts.create/store-multiaccount [id hashed-password callback]})) + ::multiaccounts.create/store-multiaccount [id key-uid hashed-password callback]})) (fx/defn recover-multiaccount-with-checks {:events [::sign-in-button-pressed]} diff --git a/src/status_im/native_module/core.cljs b/src/status_im/native_module/core.cljs index 031881d2639..53d978e2dd0 100644 --- a/src/status_im/native_module/core.cljs +++ b/src/status_im/native_module/core.cljs @@ -19,18 +19,19 @@ (.clearCookies ^js (status)) (.clearStorageAPIs ^js (status)))) -(defn init-keystore [] - (log/debug "[native-module] init-keystore") - (.initKeystore ^js (status))) +(defn init-keystore [key-uid callback] + (log/debug "[native-module] init-keystore" key-uid) + (.initKeystore ^js (status) key-uid callback)) (defn open-accounts [callback] (log/debug "[native-module] open-accounts") (.openAccounts ^js (status) #(callback (types/json->clj %)))) (defn prepare-dir-and-update-config - [config callback] + [key-uid config callback] (log/debug "[native-module] prepare-dir-and-update-config") (.prepareDirAndUpdateConfig ^js (status) + key-uid config #(callback (types/json->clj %)))) @@ -44,26 +45,32 @@ (defn save-account-and-login "NOTE: beware, the password has to be sha3 hashed" - [multiaccount-data hashed-password settings config accounts-data] + [key-uid multiaccount-data hashed-password settings config accounts-data] (log/debug "[native-module] save-account-and-login" "multiaccount-data" multiaccount-data) (clear-web-data) - (.saveAccountAndLogin - ^js (status) multiaccount-data hashed-password settings config accounts-data)) + (init-keystore + key-uid + #(.saveAccountAndLogin + ^js (status) multiaccount-data hashed-password settings config accounts-data))) (defn save-multiaccount-and-login-with-keycard "NOTE: chat-key is a whisper private key sent from keycard" - [multiaccount-data password settings config accounts-data chat-key] + [key-uid multiaccount-data password settings config accounts-data chat-key] (log/debug "[native-module] save-account-and-login-with-keycard") - (.saveAccountAndLoginWithKeycard - ^js (status) multiaccount-data password settings config accounts-data chat-key)) + (init-keystore + key-uid + #(.saveAccountAndLoginWithKeycard + ^js (status) multiaccount-data password settings config accounts-data chat-key))) (defn login "NOTE: beware, the password has to be sha3 hashed" - [account-data hashed-password] + [key-uid account-data hashed-password] (log/debug "[native-module] login") (clear-web-data) - (.login ^js (status) account-data hashed-password)) + (init-keystore + key-uid + #(.login ^js (status) account-data hashed-password))) (defn logout [] (log/debug "[native-module] logout") @@ -116,24 +123,28 @@ and chat accounts, you need to load the account again with `multiaccount-load-account` before using `multiaccount-store-derived` and the id of the account stored will have changed" - [account-id hashed-password callback] + [account-id key-uid hashed-password callback] (log/debug "[native-module] multiaccount-store-account") (when (status) - (.multiAccountStoreAccount ^js (status) - (types/clj->json {:accountID account-id - :password hashed-password}) - callback))) + (init-keystore + key-uid + #(.multiAccountStoreAccount ^js (status) + (types/clj->json {:accountID account-id + :password hashed-password}) + callback)))) (defn multiaccount-store-derived "NOTE: beware, the password has to be sha3 hashed" - [account-id paths hashed-password callback] - (log/debug "[native-module] multiaccount-store-derived" + [account-id key-uid paths hashed-password callback] + (log/debug "[native-module] multiaccount-store-derived" "account-id" account-id) - (.multiAccountStoreDerived ^js (status) - (types/clj->json {:accountID account-id - :paths paths - :password hashed-password}) - callback)) + (init-keystore + key-uid + #(.multiAccountStoreDerived ^js (status) + (types/clj->json {:accountID account-id + :paths paths + :password hashed-password}) + callback))) (defn multiaccount-generate-and-derive-addresses "used to generate multiple multiaccounts for onboarding @@ -172,10 +183,12 @@ (.verify ^js (status) address hashed-password callback)) (defn login-with-keycard - [{:keys [multiaccount-data password chat-key]}] + [{:keys [key-uid multiaccount-data password chat-key]}] (log/debug "[native-module] login-with-keycard") (clear-web-data) - (.loginWithKeycard ^js (status) multiaccount-data password chat-key)) + (init-keystore + key-uid + #(.loginWithKeycard ^js (status) multiaccount-data password chat-key))) (defn set-soft-input-mode [mode] (log/debug "[native-module] set-soft-input-mode") diff --git a/src/status_im/node/core.cljs b/src/status_im/node/core.cljs index 33aec365ead..97e7491d801 100644 --- a/src/status_im/node/core.cljs +++ b/src/status_im/node/core.cljs @@ -165,11 +165,13 @@ app-db" (fx/defn prepare-new-config "Use this function to apply settings to the current account node config" [{:keys [db]} {:keys [on-success]}] - {::prepare-new-config [(get-new-config db) - #(re-frame/dispatch - [::save-new-config % {:on-success on-success}])]}) + (let [key-uid (get-in db [:multiaccount :key-uid])] + {::prepare-new-config [key-uid + (get-new-config db) + #(re-frame/dispatch + [::save-new-config % {:on-success on-success}])]})) (re-frame/reg-fx ::prepare-new-config - (fn [[config callback]] - (status/prepare-dir-and-update-config config callback))) + (fn [[key-uid config callback]] + (status/prepare-dir-and-update-config key-uid config callback))) diff --git a/src/status_im/wallet/accounts/core.cljs b/src/status_im/wallet/accounts/core.cljs index 5aec90e174f..d93a2e1cfef 100644 --- a/src/status_im/wallet/accounts/core.cljs +++ b/src/status_im/wallet/accounts/core.cljs @@ -57,7 +57,7 @@ "/" (last (string/split path "/"))) path)) -(defn derive-and-store-account [path hashed-password type accounts] +(defn derive-and-store-account [key-uid path hashed-password type accounts] (fn [value] (let [{:keys [id error]} (types/json->clj value)] (if error @@ -71,6 +71,7 @@ (re-frame/dispatch [::new-account-error :account-error (i18n/label :t/account-exists-title)]) (status/multiaccount-store-derived id + key-uid [path] hashed-password (fn [result] @@ -87,7 +88,7 @@ (def pass-error "cannot retrieve a valid key for a given account: could not decrypt key with given password") -(defn store-account [path hashed-password type] +(defn store-account [key-uid path hashed-password type] (fn [value] (let [{:keys [id error]} (types/json->clj value)] (if error @@ -96,6 +97,7 @@ error]) (status/multiaccount-store-account id + key-uid hashed-password (account-stored path type)))))) @@ -108,38 +110,40 @@ (re-frame/reg-fx ::generate-account - (fn [{:keys [derivation-info hashed-password accounts]}] + (fn [{:keys [derivation-info hashed-password accounts key-uid]}] (let [{:keys [address path]} derivation-info] (status/multiaccount-load-account address hashed-password - (derive-and-store-account path hashed-password :generated accounts))))) + (derive-and-store-account key-uid path hashed-password :generated accounts))))) (re-frame/reg-fx ::import-account-seed - (fn [{:keys [passphrase hashed-password accounts]}] + (fn [{:keys [passphrase hashed-password accounts key-uid]}] (status/multiaccount-import-mnemonic (mnemonic/sanitize-passphrase (security/unmask passphrase)) "" - (derive-and-store-account constants/path-default-wallet hashed-password :seed accounts)))) + (derive-and-store-account key-uid constants/path-default-wallet hashed-password :seed accounts)))) (re-frame/reg-fx ::import-account-private-key - (fn [{:keys [private-key hashed-password]}] + (fn [{:keys [private-key hashed-password key-uid]}] (status/multiaccount-import-private-key (string/trim (security/unmask private-key)) - (store-account constants/path-default-wallet hashed-password :key)))) + (store-account key-uid constants/path-default-wallet hashed-password :key)))) (fx/defn generate-new-account [{:keys [db]} hashed-password] - (let [wallet-root-address (get-in db [:multiaccount :wallet-root-address]) - path-num (inc (get-in db [:multiaccount :latest-derived-path])) - accounts (:multiaccount/accounts db)] + (let [{:keys [key-uid wallet-root-address]} + (get db :multiaccount) + path-num (inc (get-in db [:multiaccount :latest-derived-path])) + accounts (:multiaccount/accounts db)] {:db (assoc-in db [:add-account :step] :generating) ::generate-account {:derivation-info {:path (str "m/" path-num) :address wallet-root-address} :hashed-password hashed-password - :accounts accounts}})) + :accounts accounts + :key-uid key-uid}})) (fx/defn import-new-account-seed [{:keys [db]} passphrase hashed-password] @@ -150,21 +154,24 @@ (fx/defn new-account-seed-validated {:events [:wallet.accounts/seed-validated]} - [cofx phrase-warnings passphrase hashed-password] - (let [error (:error (types/json->clj phrase-warnings))] + [{:keys [db] :as cofx} phrase-warnings passphrase hashed-password] + (let [error (:error (types/json->clj phrase-warnings)) + {:keys [key-uid]} (:multiaccount db)] (if-not (string/blank? error) (new-account-error cofx :account-error error) - (let [{:keys [db]} cofx - accounts (:multiaccount/accounts db)] + (let [accounts (:multiaccount/accounts db)] {::import-account-seed {:passphrase passphrase :hashed-password hashed-password - :accounts accounts}})))) + :accounts accounts + :key-uid key-uid}})))) (fx/defn import-new-account-private-key [{:keys [db]} private-key hashed-password] - {:db (assoc-in db [:add-account :step] :generating) - ::import-account-private-key {:private-key private-key - :hashed-password hashed-password}}) + (let [{:keys [key-uid]} (:multiaccount db)] + {:db (assoc-in db [:add-account :step] :generating) + ::import-account-private-key {:private-key private-key + :hashed-password hashed-password + :key-uid key-uid}})) (fx/defn save-new-account [{:keys [db] :as cofx}] diff --git a/status-go-version.json b/status-go-version.json index 996566ac453..40d3298312b 100644 --- a/status-go-version.json +++ b/status-go-version.json @@ -2,7 +2,7 @@ "_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh ' instead", "owner": "status-im", "repo": "status-go", - "version": "v0.54.1", - "commit-sha1": "20f45a7c1caa25a30853480ac47177b534536f26", - "src-sha256": "1hsjsv00dlbjp4nqnifymldr8v20arzv07l9l27jarq9dk00wbia" + "version": "v0.55.1", + "commit-sha1": "6d5a93287b2c1b4d4d5d1178a3ecec870bf18b9e", + "src-sha256": "1wly0km9bxxv1wwj6jchqh4d4x2m86fxrdqixjzldy70vl6qbyqa" }