From 8a3a281775ea6ff9335e3b51f1e8b4665ece1f5b Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sat, 20 Mar 2021 13:18:03 -0300 Subject: [PATCH] Maybe init wallet in 1st unlockwallet call (api) Unlike the UI, a daemon cannot capture the user's wallet encryption password to init an encrypted wallet and update balances. This change addresses the problem in the 1st call to the api's unlockwallet method. --- .../bisq/core/api/CoreWalletsService.java | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/bisq/core/api/CoreWalletsService.java b/core/src/main/java/bisq/core/api/CoreWalletsService.java index 7346f11956e..cdce7e68925 100644 --- a/core/src/main/java/bisq/core/api/CoreWalletsService.java +++ b/core/src/main/java/bisq/core/api/CoreWalletsService.java @@ -22,6 +22,7 @@ import bisq.core.api.model.BsqBalanceInfo; import bisq.core.api.model.BtcBalanceInfo; import bisq.core.api.model.TxFeeRateInfo; +import bisq.core.app.AppStartupState; import bisq.core.btc.Balances; import bisq.core.btc.exceptions.AddressEntryException; import bisq.core.btc.exceptions.BsqChangeBelowDustException; @@ -30,6 +31,7 @@ import bisq.core.btc.exceptions.WalletException; import bisq.core.btc.model.AddressEntry; import bisq.core.btc.model.BsqTransferModel; +import bisq.core.btc.setup.WalletsSetup; import bisq.core.btc.wallet.BsqTransferService; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BtcWalletService; @@ -89,8 +91,11 @@ @Slf4j class CoreWalletsService { + private final AppStartupState appStartupState; + private final CoreContext coreContext; private final Balances balances; private final WalletsManager walletsManager; + private final WalletsSetup walletsSetup; private final BsqWalletService bsqWalletService; private final BsqTransferService bsqTransferService; private final BsqFormatter bsqFormatter; @@ -108,8 +113,11 @@ class CoreWalletsService { private final ListeningExecutorService executor = Utilities.getSingleThreadListeningExecutor("CoreWalletsService"); @Inject - public CoreWalletsService(Balances balances, + public CoreWalletsService(AppStartupState appStartupState, + CoreContext coreContext, + Balances balances, WalletsManager walletsManager, + WalletsSetup walletsSetup, BsqWalletService bsqWalletService, BsqTransferService bsqTransferService, BsqFormatter bsqFormatter, @@ -117,8 +125,11 @@ public CoreWalletsService(Balances balances, @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, FeeService feeService, Preferences preferences) { + this.appStartupState = appStartupState; + this.coreContext = coreContext; this.balances = balances; this.walletsManager = walletsManager; + this.walletsSetup = walletsSetup; this.bsqWalletService = bsqWalletService; this.bsqTransferService = bsqTransferService; this.bsqFormatter = bsqFormatter; @@ -433,6 +444,9 @@ void unlockWallet(String password, long timeout) { lockTimer = null; } + if (coreContext.isApiUser()) + maybeInitWallet(); + lockTimer = UserThread.runAfter(() -> { if (tempAesKey != null) { // The unlockwallet timeout has expired; re-lock the wallet. @@ -458,12 +472,16 @@ void removeWalletPassword(String password) { // Throws a RuntimeException if wallets are not available (encrypted or not). void verifyWalletsAreAvailable() { + verifyWalletAndNetworkAreInitialized(); + if (!walletsManager.areWalletsAvailable()) throw new IllegalStateException("wallet is not yet available"); } // Throws a RuntimeException if wallets are not available or not encrypted. void verifyWalletIsAvailableAndEncrypted() { + verifyWalletAndNetworkAreInitialized(); + if (!walletsManager.areWalletsAvailable()) throw new IllegalStateException("wallet is not yet available"); @@ -477,6 +495,11 @@ void verifyEncryptedWalletIsUnlocked() { throw new IllegalStateException("wallet is locked"); } + void verifyWalletAndNetworkAreInitialized() { + if (!appStartupState.isWalletAndNetworkReady()) + throw new IllegalStateException("wallet and network is not yet initialized"); + } + // Throws a RuntimeException if wallet currency code is not BSQ or BTC. private void verifyWalletCurrencyCodeIsValid(String currencyCode) { if (currencyCode == null || currencyCode.isEmpty()) @@ -487,6 +510,23 @@ private void verifyWalletCurrencyCodeIsValid(String currencyCode) { throw new IllegalStateException(format("wallet does not support %s", currencyCode)); } + private void maybeInitWallet() { + // Unlike the UI, a daemon cannot capture the user's wallet encryption password + // on startup. This method will set the wallet service's aesKey if necessary, + // then update balances. + log.info("Init wallet"); + if (tempAesKey == null) + throw new IllegalStateException("cannot init encrypted wallet with null key"); + + if (btcWalletService.getAesKey() == null || bsqWalletService.getAesKey() == null) { + KeyParameter aesKey = new KeyParameter(tempAesKey.getKey()); + walletsManager.setAesKey(aesKey); + walletsSetup.getWalletConfig().maybeAddSegwitKeychain(walletsSetup.getWalletConfig().btcWallet(), aesKey); + balances.onAllServicesInitialized(); // btc specific + // TODO Init BSQ wallet. How? + } + } + private BsqBalanceInfo getBsqBalances() { verifyWalletsAreAvailable(); verifyEncryptedWalletIsUnlocked();