Merge bitcoin/bitcoin#26618: rpc: Prevent unloading a wallet when rescanning

109cbb819d doc: Add release notes for #26618 (Aurèle Oulès)
b13902d2e4 rpc: Prevent unloading a wallet when rescanning (Aurèle Oulès)

Pull request description:

  Fixes #26463.

  This PR prevents a user from unloading a wallet if it is currently rescanning.

  To test:

  ```bash
  ./src/bitcoin-cli -testnet -named createwallet wallet_name=wo disable_private_keys=true
  ./src/bitcoin-cli -testnet -rpcwallet=wo importdescriptors '[{
    "desc": "addr(mmcuW74MyJUZuLnWXGQLoNXPrS9RbFz6gD)#tpnrahgc",
        "timestamp": 0,
        "active": false,
        "internal": false,
        "next": 0
  }]'
  ./src/bitcoin-cli -testnet unloadwallet wo
  error code: -4
  error message:
  Wallet is currently rescanning. Abort existing rescan or wait.

ACKs for top commit:
  achow101:
    ACK 109cbb819d
  w0xlt:
    ACK 109cbb819d
  kouloumos:
    ACK 109cbb819d
  promag:
    ACK 109cbb819d

Tree-SHA512: 15fdddf4cf9f3fa08f52069fe4a25a76e04a55bb2586b031bfb0393dce7f175dcdb52823e132a7dff6a894539beeb980a1aad2a792790be036be6977628149b2
This commit is contained in:
Andrew Chow 2023-01-09 16:18:40 -05:00
commit 1aedc3b6c8
No known key found for this signature in database
GPG Key ID: 17565732E08E5E41
2 changed files with 17 additions and 6 deletions

View File

@ -0,0 +1,4 @@
RPC Wallet
----------
- RPC `unloadwallet` now fails if a rescan is in progress. (#26618)

View File

@ -445,13 +445,20 @@ static RPCHelpMan unloadwallet()
throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
}
// Release the "main" shared pointer and prevent further notifications.
// Note that any attempt to load the same wallet would fail until the wallet
// is destroyed (see CheckUniqueFileid).
std::vector<bilingual_str> warnings;
std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
{
WalletRescanReserver reserver(*wallet);
if (!reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
}
// Release the "main" shared pointer and prevent further notifications.
// Note that any attempt to load the same wallet would fail until the wallet
// is destroyed (see CheckUniqueFileid).
std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
}
}
UnloadWallet(std::move(wallet));