From 087bd1d20d52f69c39b73399ba422b5b58dcf798 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Mon, 27 Jul 2020 20:42:57 -0400 Subject: [PATCH] fix: generate wallet addresses --- src/status/libstatus/accounts.nim | 45 +++++++++++++++++++++++++++---- src/status/libstatus/types.nim | 2 ++ src/status/wallet.nim | 29 ++++++++++++++------ vendor/nim-status | 2 +- 4 files changed, 64 insertions(+), 14 deletions(-) diff --git a/src/status/libstatus/accounts.nim b/src/status/libstatus/accounts.nim index ab97343bea..3ceba0c8ff 100644 --- a/src/status/libstatus/accounts.nim +++ b/src/status/libstatus/accounts.nim @@ -99,11 +99,11 @@ proc saveAccountAndLogin*( raise newException(StatusGoException, "Error saving account and logging in: " & error) -proc storeDerivedAccounts*(account: GeneratedAccount, password: string): MultiAccounts = +proc storeDerivedAccounts*(account: GeneratedAccount, password: string, paths: seq[string] = @[PATH_WALLET_ROOT, PATH_EIP_1581, PATH_WHISPER, PATH_DEFAULT_WALLET]): MultiAccounts = let hashedPassword = hashPassword(password) let multiAccount = %* { "accountID": account.id, - "paths": [PATH_WALLET_ROOT, PATH_EIP_1581, PATH_WHISPER, PATH_DEFAULT_WALLET], + "paths": paths, "password": hashedPassword } let response = $nim_status.multiAccountStoreDerivedAccounts($multiAccount); @@ -180,6 +180,15 @@ proc login*(nodeAccount: NodeAccount, password: string): NodeAccount = raise newException(StatusGoException, "Error logging in: " & error) +proc loadAccount*(address: string, password: string): GeneratedAccount = + let hashedPassword = hashPassword(password) + let inputJson = %* { + "address": address, + "password": hashedPassword + } + let loadResult = $nim_status.multiAccountLoadAccount($inputJson) + result = Json.decode(loadResult, GeneratedAccount) + proc verifyAccountPassword*(address: string, password: string): bool = let hashedPassword = hashPassword(password) let verifyResult = $nim_status.verifyAccountPassword(KEYSTOREDIR, address, hashedPassword) @@ -210,11 +219,26 @@ proc MultiAccountImportPrivateKey*(privateKey: string): GeneratedAccount = except Exception as e: error "Error getting account from private key", msg=e.msg -proc saveAccount*(account: GeneratedAccount, password: string, color: string, accountType: string, isADerivedAccount = true): DerivedAccount = + +proc storeDerivedWallet*(account: GeneratedAccount, password: string, walletIndex: int) = + let hashedPassword = hashPassword(password) + let multiAccount = %* { + "accountID": account.id, + "paths": ["m/" & $walletIndex], + "password": hashedPassword + } + let response = parseJson($nim_status.multiAccountStoreDerivedAccounts($multiAccount)); + let error = response{"error"}.getStr + if error == "": + debug "Wallet stored succesfully" + return + raise newException(StatusGoException, "Error storing wallet: " & error) + +proc saveAccount*(account: GeneratedAccount, password: string, color: string, accountType: string, isADerivedAccount = true, walletIndex: int = 0 ): DerivedAccount = try: # Only store derived accounts. Private key accounts are not multiaccounts if (isADerivedAccount): - discard storeDerivedAccounts(account, password) + storeDerivedWallet(account, password, walletIndex) var address = account.derived.defaultWallet.address var publicKey = account.derived.defaultWallet.publicKey @@ -230,7 +254,7 @@ proc saveAccount*(account: GeneratedAccount, password: string, color: string, ac "address": address, "public-key": publicKey, "type": accountType, - "path": "m/44'/60'/0'/0/1" + "path": "m/44'/60'/0'/0/" & $walletIndex }] ]) @@ -267,6 +291,17 @@ proc deleteAccount*(address: string): string = error "Error removing the account", msg=e.msg result = e.msg +proc deriveWallet*(accountId: string, walletIndex: int): DerivedAccount = + let path = "m/" & $walletIndex + let deriveJson = %* { + "accountID": accountId, + "paths": [path] + } + let deriveResult = parseJson($nim_status.multiAccountDeriveAddresses($deriveJson)) + result = DerivedAccount( + address: deriveResult[path]["address"].getStr, + publicKey: deriveResult[path]["publicKey"].getStr) + proc deriveAccounts*(accountId: string): MultiAccounts = let deriveJson = %* { "accountID": accountId, diff --git a/src/status/libstatus/types.nim b/src/status/libstatus/types.nim index 734839fab6..324abcc5be 100644 --- a/src/status/libstatus/types.nim +++ b/src/status/libstatus/types.nim @@ -148,6 +148,8 @@ type PublicKey = "public-key" Stickers_PacksInstalled = "stickers/packs-installed" Stickers_Recent = "stickers/recent-stickers" + WalletRootAddress = "wallet-root-address" + LatestDerivedPath = "latest-derived-path" UpstreamConfig* = ref object enabled* {.serializedFieldName("Enabled").}: bool diff --git a/src/status/wallet.nim b/src/status/wallet.nim index 0483841dec..3615d11ecb 100644 --- a/src/status/wallet.nim +++ b/src/status/wallet.nim @@ -1,4 +1,5 @@ import eventemitter, json, strformat, strutils, chronicles, sequtils +import json_serialization from eth/common/utils import parseAddress import libstatus/accounts as status_accounts import libstatus/tokens as status_tokens @@ -100,10 +101,10 @@ proc calculateTotalFiatBalance*(self: WalletModel) = for account in self.accounts: self.totalBalance += account.realFiatBalance -proc addNewGeneratedAccount(self: WalletModel, generatedAccount: GeneratedAccount, password: string, accountName: string, color: string, accountType: string, isADerivedAccount = true): string = +proc addNewGeneratedAccount(self: WalletModel, generatedAccount: GeneratedAccount, password: string, accountName: string, color: string, accountType: string, isADerivedAccount = true, walletIndex: int = 0): string = try: generatedAccount.name = accountName - var derivedAccount: DerivedAccount = status_accounts.saveAccount(generatedAccount, password, color, accountType, isADerivedAccount) + var derivedAccount: DerivedAccount = status_accounts.saveAccount(generatedAccount, password, color, accountType, isADerivedAccount, walletIndex) var account = self.newAccount(accountName, derivedAccount.address, color, fmt"0.00 {self.defaultCurrency}", derivedAccount.publicKey) self.accounts.add(account) self.events.emit("newAccountAdded", AccountArgs(account: account)) @@ -112,19 +113,31 @@ proc addNewGeneratedAccount(self: WalletModel, generatedAccount: GeneratedAccoun return "" -proc addNewGeneratedAccountWithPassword(self: WalletModel, generatedAccount: GeneratedAccount, password: string, accountName: string, color: string, accountType: string, isADerivedAccount = true): string = +proc addNewGeneratedAccountWithPassword(self: WalletModel, generatedAccount: GeneratedAccount, password: string, accountName: string, color: string, accountType: string, isADerivedAccount = true, walletIndex: int = 0): string = let defaultAccount = status_accounts.getDefaultAccount() let isPasswordOk = status_accounts.verifyAccountPassword(defaultAccount, password) if (not isPasswordOk): return "Wrong password" - - result = self.addNewGeneratedAccount(generatedAccount, password, accountName, color, accountType, isADerivedAccount) + result = self.addNewGeneratedAccount(generatedAccount, password, accountName, color, accountType, isADerivedAccount, walletIndex) proc generateNewAccount*(self: WalletModel, password: string, accountName: string, color: string): string = - let accounts = status_accounts.generateAddresses(1) - let generatedAccount = accounts[0] - return self.addNewGeneratedAccountWithPassword(generatedAccount, password, accountName, color, constants.GENERATED) + let walletRootAddress = status_settings.getSetting[string](Setting.WalletRootAddress, "") + let walletIndex = status_settings.getSetting[int](Setting.LatestDerivedPath) + 1 + let loadedAccount = status_accounts.loadAccount(walletRootAddress, password) + let derivedAccount = status_accounts.deriveWallet(loadedAccount.id, walletIndex) + + let generatedAccount = GeneratedAccount( + id: loadedAccount.id, + publicKey: derivedAccount.publicKey, + address: derivedAccount.address + ) + + result = self.addNewGeneratedAccountWithPassword(generatedAccount, password, accountName, color, constants.GENERATED, true, walletIndex) + + let statusGoResult = status_settings.saveSetting(Setting.LatestDerivedPath, $walletIndex) + if statusGoResult.error != "": + error "Error storing the latest wallet index", msg=statusGoResult.error proc addAccountsFromSeed*(self: WalletModel, seed: string, password: string, accountName: string, color: string): string = let mnemonic = replace(seed, ',', ' ') diff --git a/vendor/nim-status b/vendor/nim-status index cffc38c9fa..b3e3a8920b 160000 --- a/vendor/nim-status +++ b/vendor/nim-status @@ -1 +1 @@ -Subproject commit cffc38c9fa0dd570cc3676dd32cfcc92c04b7c86 +Subproject commit b3e3a8920b79a5a75c6680730c7f75e6201afde7