Merge #21331: rpc: replace wallet raw pointers with references (#18592 rebased)

7c90c67b7e rpc: refactor rpc wallet functions to take references instead of pointers (fanquake)
4866934008 rpc: remove calls to CWallet.get() (fanquake)

Pull request description:

  This is a rebased #18592.

  > This PR replaces raw pointers in `rpcwallet.cpp` and `rpcdump.cpp` with **shared_ptr**. The motivation for this PR is described here https://github.com/bitcoin/bitcoin/issues/18590

  > It seems that this PR is indirectly related to this issue: https://github.com/bitcoin/bitcoin/pull/13063#discussion_r186740049

  > Notice: I have deliberately **not** changed the class `WalletRescanReserver ` whose constructor expects a raw pointer, because it's external and affects other areas, which I didn't touch to avoid making this PR "viral".

  > Fixes https://github.com/bitcoin/bitcoin/issues/18590

ACKs for top commit:
  MarcoFalke:
    ACK 7c90c67b7e 🐧
  ryanofsky:
    Code review ACK 7c90c67b7e. Changes easy to review with `--word-diff-regex=. -U0`

Tree-SHA512: 32d69c813026b02260e8a89de9d6a5ab9e87826ba230687246583ac7a80c8c3fd00318da4658f1450e04c23d2c77ae765862de0d2a110b1312b3b69a1161e7ba
This commit is contained in:
MarcoFalke 2021-03-10 08:24:47 +01:00
commit eea6196c3d
No known key found for this signature in database
GPG key ID: D2EA4850E7528B25
3 changed files with 190 additions and 241 deletions

View file

@ -56,13 +56,13 @@ static std::string DecodeDumpString(const std::string &str) {
return ret.str(); return ret.str();
} }
static bool GetWalletAddressesForKey(LegacyScriptPubKeyMan* spk_man, const CWallet* const pwallet, const CKeyID& keyid, std::string& strAddr, std::string& strLabel) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) static bool GetWalletAddressesForKey(LegacyScriptPubKeyMan* spk_man, const CWallet& wallet, const CKeyID& keyid, std::string& strAddr, std::string& strLabel) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{ {
bool fLabelFound = false; bool fLabelFound = false;
CKey key; CKey key;
spk_man->GetKey(keyid, key); spk_man->GetKey(keyid, key);
for (const auto& dest : GetAllDestinationsForKey(key.GetPubKey())) { for (const auto& dest : GetAllDestinationsForKey(key.GetPubKey())) {
const auto* address_book_entry = pwallet->FindAddressBookEntry(dest); const auto* address_book_entry = wallet.FindAddressBookEntry(dest);
if (address_book_entry) { if (address_book_entry) {
if (!strAddr.empty()) { if (!strAddr.empty()) {
strAddr += ","; strAddr += ",";
@ -73,7 +73,7 @@ static bool GetWalletAddressesForKey(LegacyScriptPubKeyMan* spk_man, const CWall
} }
} }
if (!fLabelFound) { if (!fLabelFound) {
strAddr = EncodeDestination(GetDestinationForKey(key.GetPubKey(), pwallet->m_default_address_type)); strAddr = EncodeDestination(GetDestinationForKey(key.GetPubKey(), wallet.m_default_address_type));
} }
return fLabelFound; return fLabelFound;
} }
@ -118,22 +118,21 @@ RPCHelpMan importprivkey()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled"); throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled");
} }
EnsureLegacyScriptPubKeyMan(*wallet, true); EnsureLegacyScriptPubKeyMan(*pwallet, true);
WalletRescanReserver reserver(*pwallet); WalletRescanReserver reserver(*pwallet);
bool fRescan = true; bool fRescan = true;
{ {
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet); EnsureWalletIsUnlocked(*pwallet);
std::string strSecret = request.params[0].get_str(); std::string strSecret = request.params[0].get_str();
std::string strLabel = ""; std::string strLabel = "";
@ -210,9 +209,8 @@ RPCHelpMan abortrescan()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false; if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false;
pwallet->AbortRescan(); pwallet->AbortRescan();
@ -249,9 +247,8 @@ RPCHelpMan importaddress()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
EnsureLegacyScriptPubKeyMan(*pwallet, true); EnsureLegacyScriptPubKeyMan(*pwallet, true);
@ -335,9 +332,8 @@ RPCHelpMan importprunedfunds()
RPCExamples{""}, RPCExamples{""},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
CMutableTransaction tx; CMutableTransaction tx;
if (!DecodeHexTx(tx, request.params[0].get_str())) { if (!DecodeHexTx(tx, request.params[0].get_str())) {
@ -397,9 +393,8 @@ RPCHelpMan removeprunedfunds()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
@ -445,11 +440,10 @@ RPCHelpMan importpubkey()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
EnsureLegacyScriptPubKeyMan(*wallet, true); EnsureLegacyScriptPubKeyMan(*pwallet, true);
std::string strLabel; std::string strLabel;
if (!request.params[1].isNull()) if (!request.params[1].isNull())
@ -527,11 +521,10 @@ RPCHelpMan importwallet()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
EnsureLegacyScriptPubKeyMan(*wallet, true); EnsureLegacyScriptPubKeyMan(*pwallet, true);
if (pwallet->chain().havePruned()) { if (pwallet->chain().havePruned()) {
// Exit early and print an error. // Exit early and print an error.
@ -550,7 +543,7 @@ RPCHelpMan importwallet()
{ {
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet); EnsureWalletIsUnlocked(*pwallet);
fsbridge::ifstream file; fsbridge::ifstream file;
file.open(request.params[0].get_str(), std::ios::in | std::ios::ate); file.open(request.params[0].get_str(), std::ios::in | std::ios::ate);
@ -684,15 +677,14 @@ RPCHelpMan dumpprivkey()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*wallet); LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet);
LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore); LOCK2(pwallet->cs_wallet, spk_man.cs_KeyStore);
EnsureWalletIsUnlocked(pwallet); EnsureWalletIsUnlocked(*pwallet);
std::string strAddress = request.params[0].get_str(); std::string strAddress = request.params[0].get_str();
CTxDestination dest = DecodeDestination(strAddress); CTxDestination dest = DecodeDestination(strAddress);
@ -747,7 +739,7 @@ RPCHelpMan dumpwallet()
LOCK2(wallet.cs_wallet, spk_man.cs_KeyStore); LOCK2(wallet.cs_wallet, spk_man.cs_KeyStore);
EnsureWalletIsUnlocked(&wallet); EnsureWalletIsUnlocked(wallet);
fs::path filepath = request.params[0].get_str(); fs::path filepath = request.params[0].get_str();
filepath = fs::absolute(filepath); filepath = fs::absolute(filepath);
@ -809,7 +801,7 @@ RPCHelpMan dumpwallet()
CKey key; CKey key;
if (spk_man.GetKey(keyid, key)) { if (spk_man.GetKey(keyid, key)) {
file << strprintf("%s %s ", EncodeSecret(key), strTime); file << strprintf("%s %s ", EncodeSecret(key), strTime);
if (GetWalletAddressesForKey(&spk_man, &wallet, keyid, strAddr, strLabel)) { if (GetWalletAddressesForKey(&spk_man, wallet, keyid, strAddr, strLabel)) {
file << strprintf("label=%s", strLabel); file << strprintf("label=%s", strLabel);
} else if (keyid == seed_id) { } else if (keyid == seed_id) {
file << "hdseed=1"; file << "hdseed=1";
@ -1169,7 +1161,7 @@ static UniValue ProcessImportDescriptor(ImportData& import_data, std::map<CKeyID
return warnings; return warnings;
} }
static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) static UniValue ProcessImport(CWallet& wallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{ {
UniValue warnings(UniValue::VARR); UniValue warnings(UniValue::VARR);
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
@ -1184,7 +1176,7 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
const bool add_keypool = data.exists("keypool") ? data["keypool"].get_bool() : false; const bool add_keypool = data.exists("keypool") ? data["keypool"].get_bool() : false;
// Add to keypool only works with privkeys disabled // Add to keypool only works with privkeys disabled
if (add_keypool && !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { if (add_keypool && !wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Keys can only be imported to the keypool when private keys are disabled"); throw JSONRPCError(RPC_INVALID_PARAMETER, "Keys can only be imported to the keypool when private keys are disabled");
} }
@ -1206,29 +1198,29 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
} }
// If private keys are disabled, abort if private keys are being imported // If private keys are disabled, abort if private keys are being imported
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !privkey_map.empty()) { if (wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !privkey_map.empty()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled"); throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled");
} }
// Check whether we have any work to do // Check whether we have any work to do
for (const CScript& script : script_pub_keys) { for (const CScript& script : script_pub_keys) {
if (pwallet->IsMine(script) & ISMINE_SPENDABLE) { if (wallet.IsMine(script) & ISMINE_SPENDABLE) {
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script (\"" + HexStr(script) + "\")"); throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script (\"" + HexStr(script) + "\")");
} }
} }
// All good, time to import // All good, time to import
pwallet->MarkDirty(); wallet.MarkDirty();
if (!pwallet->ImportScripts(import_data.import_scripts, timestamp)) { if (!wallet.ImportScripts(import_data.import_scripts, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding script to wallet"); throw JSONRPCError(RPC_WALLET_ERROR, "Error adding script to wallet");
} }
if (!pwallet->ImportPrivKeys(privkey_map, timestamp)) { if (!wallet.ImportPrivKeys(privkey_map, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
} }
if (!pwallet->ImportPubKeys(ordered_pubkeys, pubkey_map, import_data.key_origins, add_keypool, internal, timestamp)) { if (!wallet.ImportPubKeys(ordered_pubkeys, pubkey_map, import_data.key_origins, add_keypool, internal, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
} }
if (!pwallet->ImportScriptPubKeys(label, script_pub_keys, have_solving_data, !internal, timestamp)) { if (!wallet.ImportScriptPubKeys(label, script_pub_keys, have_solving_data, !internal, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
} }
@ -1336,13 +1328,12 @@ RPCHelpMan importmulti()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& mainRequest) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& mainRequest) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(mainRequest); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(mainRequest);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ}); RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ});
EnsureLegacyScriptPubKeyMan(*wallet, true); EnsureLegacyScriptPubKeyMan(*pwallet, true);
const UniValue& requests = mainRequest.params[0]; const UniValue& requests = mainRequest.params[0];
@ -1368,7 +1359,7 @@ RPCHelpMan importmulti()
UniValue response(UniValue::VARR); UniValue response(UniValue::VARR);
{ {
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet); EnsureWalletIsUnlocked(*pwallet);
// Verify all timestamps are present before importing any keys. // Verify all timestamps are present before importing any keys.
CHECK_NONFATAL(pwallet->chain().findBlock(pwallet->GetLastBlockHash(), FoundBlock().time(nLowestTimestamp).mtpTime(now))); CHECK_NONFATAL(pwallet->chain().findBlock(pwallet->GetLastBlockHash(), FoundBlock().time(nLowestTimestamp).mtpTime(now)));
@ -1380,7 +1371,7 @@ RPCHelpMan importmulti()
for (const UniValue& data : requests.getValues()) { for (const UniValue& data : requests.getValues()) {
const int64_t timestamp = std::max(GetImportTimestamp(data, now), minimumTimestamp); const int64_t timestamp = std::max(GetImportTimestamp(data, now), minimumTimestamp);
const UniValue result = ProcessImport(pwallet, data, timestamp); const UniValue result = ProcessImport(*pwallet, data, timestamp);
response.push_back(result); response.push_back(result);
if (!fRescan) { if (!fRescan) {
@ -1447,7 +1438,7 @@ RPCHelpMan importmulti()
}; };
} }
static UniValue ProcessDescriptorImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) static UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{ {
UniValue warnings(UniValue::VARR); UniValue warnings(UniValue::VARR);
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
@ -1516,7 +1507,7 @@ static UniValue ProcessDescriptorImport(CWallet * const pwallet, const UniValue&
} }
// If the wallet disabled private keys, abort if private keys exist // If the wallet disabled private keys, abort if private keys exist
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !keys.keys.empty()) { if (wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !keys.keys.empty()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled"); throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled");
} }
@ -1540,7 +1531,7 @@ static UniValue ProcessDescriptorImport(CWallet * const pwallet, const UniValue&
} }
// If private keys are enabled, check some things. // If private keys are enabled, check some things.
if (!pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { if (!wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
if (keys.keys.empty()) { if (keys.keys.empty()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import descriptor without private keys to a wallet with private keys enabled"); throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import descriptor without private keys to a wallet with private keys enabled");
} }
@ -1552,7 +1543,7 @@ static UniValue ProcessDescriptorImport(CWallet * const pwallet, const UniValue&
WalletDescriptor w_desc(std::move(parsed_desc), timestamp, range_start, range_end, next_index); WalletDescriptor w_desc(std::move(parsed_desc), timestamp, range_start, range_end, next_index);
// Check if the wallet already contains the descriptor // Check if the wallet already contains the descriptor
auto existing_spk_manager = pwallet->GetDescriptorScriptPubKeyMan(w_desc); auto existing_spk_manager = wallet.GetDescriptorScriptPubKeyMan(w_desc);
if (existing_spk_manager) { if (existing_spk_manager) {
LOCK(existing_spk_manager->cs_desc_man); LOCK(existing_spk_manager->cs_desc_man);
if (range_start > existing_spk_manager->GetWalletDescriptor().range_start) { if (range_start > existing_spk_manager->GetWalletDescriptor().range_start) {
@ -1561,7 +1552,7 @@ static UniValue ProcessDescriptorImport(CWallet * const pwallet, const UniValue&
} }
// Add descriptor to the wallet // Add descriptor to the wallet
auto spk_manager = pwallet->AddWalletDescriptor(w_desc, keys, label, internal); auto spk_manager = wallet.AddWalletDescriptor(w_desc, keys, label, internal);
if (spk_manager == nullptr) { if (spk_manager == nullptr) {
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Could not add descriptor '%s'", descriptor)); throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Could not add descriptor '%s'", descriptor));
} }
@ -1571,7 +1562,7 @@ static UniValue ProcessDescriptorImport(CWallet * const pwallet, const UniValue&
if (!w_desc.descriptor->GetOutputType()) { if (!w_desc.descriptor->GetOutputType()) {
warnings.push_back("Unknown output type, cannot set descriptor to active."); warnings.push_back("Unknown output type, cannot set descriptor to active.");
} else { } else {
pwallet->AddActiveScriptPubKeyMan(spk_manager->GetID(), *w_desc.descriptor->GetOutputType(), internal); wallet.AddActiveScriptPubKeyMan(spk_manager->GetID(), *w_desc.descriptor->GetOutputType(), internal);
} }
} }
@ -1641,9 +1632,8 @@ RPCHelpMan importdescriptors()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& main_request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& main_request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(main_request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(main_request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
// Make sure wallet is a descriptor wallet // Make sure wallet is a descriptor wallet
if (!pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) { if (!pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
@ -1665,7 +1655,7 @@ RPCHelpMan importdescriptors()
UniValue response(UniValue::VARR); UniValue response(UniValue::VARR);
{ {
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet); EnsureWalletIsUnlocked(*pwallet);
CHECK_NONFATAL(pwallet->chain().findBlock(pwallet->GetLastBlockHash(), FoundBlock().time(lowest_timestamp).mtpTime(now))); CHECK_NONFATAL(pwallet->chain().findBlock(pwallet->GetLastBlockHash(), FoundBlock().time(lowest_timestamp).mtpTime(now)));
@ -1673,7 +1663,7 @@ RPCHelpMan importdescriptors()
for (const UniValue& request : requests.getValues()) { for (const UniValue& request : requests.getValues()) {
// This throws an error if "timestamp" doesn't exist // This throws an error if "timestamp" doesn't exist
const int64_t timestamp = std::max(GetImportTimestamp(request, now), minimum_timestamp); const int64_t timestamp = std::max(GetImportTimestamp(request, now), minimum_timestamp);
const UniValue result = ProcessDescriptorImport(pwallet, request, timestamp); const UniValue result = ProcessDescriptorImport(*pwallet, request, timestamp);
response.push_back(result); response.push_back(result);
if (lowest_timestamp > timestamp ) { if (lowest_timestamp > timestamp ) {
@ -1775,7 +1765,7 @@ RPCHelpMan listdescriptors()
throw JSONRPCError(RPC_WALLET_ERROR, "listdescriptors is not available for non-descriptor wallets"); throw JSONRPCError(RPC_WALLET_ERROR, "listdescriptors is not available for non-descriptor wallets");
} }
EnsureWalletIsUnlocked(wallet.get()); EnsureWalletIsUnlocked(*wallet);
LOCK(wallet->cs_wallet); LOCK(wallet->cs_wallet);

View file

@ -48,8 +48,8 @@ using interfaces::FoundBlock;
static const std::string WALLET_ENDPOINT_BASE = "/wallet/"; static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
static const std::string HELP_REQUIRING_PASSPHRASE{"\nRequires wallet passphrase to be set with walletpassphrase call if wallet is encrypted.\n"}; static const std::string HELP_REQUIRING_PASSPHRASE{"\nRequires wallet passphrase to be set with walletpassphrase call if wallet is encrypted.\n"};
static inline bool GetAvoidReuseFlag(const CWallet* const pwallet, const UniValue& param) { static inline bool GetAvoidReuseFlag(const CWallet& wallet, const UniValue& param) {
bool can_avoid_reuse = pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE); bool can_avoid_reuse = wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
bool avoid_reuse = param.isNull() ? can_avoid_reuse : param.get_bool(); bool avoid_reuse = param.isNull() ? can_avoid_reuse : param.get_bool();
if (avoid_reuse && !can_avoid_reuse) { if (avoid_reuse && !can_avoid_reuse) {
@ -64,11 +64,11 @@ static inline bool GetAvoidReuseFlag(const CWallet* const pwallet, const UniValu
* We default to true for watchonly wallets if include_watchonly isn't * We default to true for watchonly wallets if include_watchonly isn't
* explicitly set. * explicitly set.
*/ */
static bool ParseIncludeWatchonly(const UniValue& include_watchonly, const CWallet& pwallet) static bool ParseIncludeWatchonly(const UniValue& include_watchonly, const CWallet& wallet)
{ {
if (include_watchonly.isNull()) { if (include_watchonly.isNull()) {
// if include_watchonly isn't explicitly set, then check if we have a watchonly wallet // if include_watchonly isn't explicitly set, then check if we have a watchonly wallet
return pwallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS); return wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
} }
// otherwise return whatever include_watchonly was set to // otherwise return whatever include_watchonly was set to
@ -117,9 +117,9 @@ std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& reques
"Wallet file not specified (must request wallet RPC through /wallet/<filename> uri-path)."); "Wallet file not specified (must request wallet RPC through /wallet/<filename> uri-path).");
} }
void EnsureWalletIsUnlocked(const CWallet* pwallet) void EnsureWalletIsUnlocked(const CWallet& wallet)
{ {
if (pwallet->IsLocked()) { if (wallet.IsLocked()) {
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
} }
} }
@ -249,9 +249,8 @@ static RPCHelpMan getnewaddress()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
@ -299,9 +298,8 @@ static RPCHelpMan getrawchangeaddress()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
@ -342,9 +340,8 @@ static RPCHelpMan setlabel()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
@ -396,13 +393,13 @@ void ParseRecipients(const UniValue& address_amounts, const UniValue& subtract_f
} }
} }
UniValue SendMoney(CWallet* const pwallet, const CCoinControl &coin_control, std::vector<CRecipient> &recipients, mapValue_t map_value, bool verbose) UniValue SendMoney(CWallet& wallet, const CCoinControl &coin_control, std::vector<CRecipient> &recipients, mapValue_t map_value, bool verbose)
{ {
EnsureWalletIsUnlocked(pwallet); EnsureWalletIsUnlocked(wallet);
// This function is only used by sendtoaddress and sendmany. // This function is only used by sendtoaddress and sendmany.
// This should always try to sign, if we don't have private keys, don't try to do anything here. // This should always try to sign, if we don't have private keys, don't try to do anything here.
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { if (wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet"); throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
} }
@ -415,11 +412,11 @@ UniValue SendMoney(CWallet* const pwallet, const CCoinControl &coin_control, std
bilingual_str error; bilingual_str error;
CTransactionRef tx; CTransactionRef tx;
FeeCalculation fee_calc_out; FeeCalculation fee_calc_out;
const bool fCreated = pwallet->CreateTransaction(recipients, tx, nFeeRequired, nChangePosRet, error, coin_control, fee_calc_out, true); const bool fCreated = wallet.CreateTransaction(recipients, tx, nFeeRequired, nChangePosRet, error, coin_control, fee_calc_out, true);
if (!fCreated) { if (!fCreated) {
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, error.original); throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, error.original);
} }
pwallet->CommitTransaction(tx, std::move(map_value), {} /* orderForm */); wallet.CommitTransaction(tx, std::move(map_value), {} /* orderForm */);
if (verbose) { if (verbose) {
UniValue entry(UniValue::VOBJ); UniValue entry(UniValue::VOBJ);
entry.pushKV("txid", tx->GetHash().GetHex()); entry.pushKV("txid", tx->GetHash().GetHex());
@ -480,9 +477,8 @@ static RPCHelpMan sendtoaddress()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -507,13 +503,13 @@ static RPCHelpMan sendtoaddress()
coin_control.m_signal_bip125_rbf = request.params[5].get_bool(); coin_control.m_signal_bip125_rbf = request.params[5].get_bool();
} }
coin_control.m_avoid_address_reuse = GetAvoidReuseFlag(pwallet, request.params[8]); coin_control.m_avoid_address_reuse = GetAvoidReuseFlag(*pwallet, request.params[8]);
// We also enable partial spend avoidance if reuse avoidance is set. // We also enable partial spend avoidance if reuse avoidance is set.
coin_control.m_avoid_partial_spends |= coin_control.m_avoid_address_reuse; coin_control.m_avoid_partial_spends |= coin_control.m_avoid_address_reuse;
SetFeeEstimateMode(*pwallet, coin_control, /* conf_target */ request.params[6], /* estimate_mode */ request.params[7], /* fee_rate */ request.params[9], /* override_min_fee */ false); SetFeeEstimateMode(*pwallet, coin_control, /* conf_target */ request.params[6], /* estimate_mode */ request.params[7], /* fee_rate */ request.params[9], /* override_min_fee */ false);
EnsureWalletIsUnlocked(pwallet); EnsureWalletIsUnlocked(*pwallet);
UniValue address_amounts(UniValue::VOBJ); UniValue address_amounts(UniValue::VOBJ);
const std::string address = request.params[0].get_str(); const std::string address = request.params[0].get_str();
@ -527,7 +523,7 @@ static RPCHelpMan sendtoaddress()
ParseRecipients(address_amounts, subtractFeeFromAmount, recipients); ParseRecipients(address_amounts, subtractFeeFromAmount, recipients);
const bool verbose{request.params[10].isNull() ? false : request.params[10].get_bool()}; const bool verbose{request.params[10].isNull() ? false : request.params[10].get_bool()};
return SendMoney(pwallet, coin_control, recipients, mapValue, verbose); return SendMoney(*pwallet, coin_control, recipients, mapValue, verbose);
}, },
}; };
} }
@ -559,9 +555,8 @@ static RPCHelpMan listaddressgroupings()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -617,13 +612,12 @@ static RPCHelpMan signmessage()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet); EnsureWalletIsUnlocked(*pwallet);
std::string strAddress = request.params[0].get_str(); std::string strAddress = request.params[0].get_str();
std::string strMessage = request.params[1].get_str(); std::string strMessage = request.params[1].get_str();
@ -720,9 +714,8 @@ static RPCHelpMan getreceivedbyaddress()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -759,9 +752,8 @@ static RPCHelpMan getreceivedbylabel()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -800,9 +792,8 @@ static RPCHelpMan getbalance()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -822,7 +813,7 @@ static RPCHelpMan getbalance()
bool include_watchonly = ParseIncludeWatchonly(request.params[2], *pwallet); bool include_watchonly = ParseIncludeWatchonly(request.params[2], *pwallet);
bool avoid_reuse = GetAvoidReuseFlag(pwallet, request.params[3]); bool avoid_reuse = GetAvoidReuseFlag(*pwallet, request.params[3]);
const auto bal = pwallet->GetBalance(min_depth, avoid_reuse); const auto bal = pwallet->GetBalance(min_depth, avoid_reuse);
@ -840,9 +831,8 @@ static RPCHelpMan getunconfirmedbalance()
RPCExamples{""}, RPCExamples{""},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -911,9 +901,8 @@ static RPCHelpMan sendmany()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -945,7 +934,7 @@ static RPCHelpMan sendmany()
ParseRecipients(sendTo, subtractFeeFromAmount, recipients); ParseRecipients(sendTo, subtractFeeFromAmount, recipients);
const bool verbose{request.params[9].isNull() ? false : request.params[9].get_bool()}; const bool verbose{request.params[9].isNull() ? false : request.params[9].get_bool()};
return SendMoney(pwallet, coin_control, recipients, std::move(mapValue), verbose); return SendMoney(*pwallet, coin_control, recipients, std::move(mapValue), verbose);
}, },
}; };
} }
@ -985,9 +974,8 @@ static RPCHelpMan addmultisigaddress()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet); LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet);
@ -1045,7 +1033,7 @@ struct tallyitem
} }
}; };
static UniValue ListReceived(const CWallet* const pwallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) static UniValue ListReceived(const CWallet& wallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{ {
// Minimum confirmations // Minimum confirmations
int nMinDepth = 1; int nMinDepth = 1;
@ -1059,7 +1047,7 @@ static UniValue ListReceived(const CWallet* const pwallet, const UniValue& param
isminefilter filter = ISMINE_SPENDABLE; isminefilter filter = ISMINE_SPENDABLE;
if (ParseIncludeWatchonly(params[2], *pwallet)) { if (ParseIncludeWatchonly(params[2], wallet)) {
filter |= ISMINE_WATCH_ONLY; filter |= ISMINE_WATCH_ONLY;
} }
@ -1075,10 +1063,10 @@ static UniValue ListReceived(const CWallet* const pwallet, const UniValue& param
// Tally // Tally
std::map<CTxDestination, tallyitem> mapTally; std::map<CTxDestination, tallyitem> mapTally;
for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) { for (const std::pair<const uint256, CWalletTx>& pairWtx : wallet.mapWallet) {
const CWalletTx& wtx = pairWtx.second; const CWalletTx& wtx = pairWtx.second;
if (wtx.IsCoinBase() || !pwallet->chain().checkFinalTx(*wtx.tx)) { if (wtx.IsCoinBase() || !wallet.chain().checkFinalTx(*wtx.tx)) {
continue; continue;
} }
@ -1096,7 +1084,7 @@ static UniValue ListReceived(const CWallet* const pwallet, const UniValue& param
continue; continue;
} }
isminefilter mine = pwallet->IsMine(address); isminefilter mine = wallet.IsMine(address);
if(!(mine & filter)) if(!(mine & filter))
continue; continue;
@ -1115,11 +1103,11 @@ static UniValue ListReceived(const CWallet* const pwallet, const UniValue& param
// Create m_address_book iterator // Create m_address_book iterator
// If we aren't filtering, go from begin() to end() // If we aren't filtering, go from begin() to end()
auto start = pwallet->m_address_book.begin(); auto start = wallet.m_address_book.begin();
auto end = pwallet->m_address_book.end(); auto end = wallet.m_address_book.end();
// If we are filtering, find() the applicable entry // If we are filtering, find() the applicable entry
if (has_filtered_address) { if (has_filtered_address) {
start = pwallet->m_address_book.find(filtered_address); start = wallet.m_address_book.find(filtered_address);
if (start != end) { if (start != end) {
end = std::next(start); end = std::next(start);
} }
@ -1227,9 +1215,8 @@ static RPCHelpMan listreceivedbyaddress()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -1237,7 +1224,7 @@ static RPCHelpMan listreceivedbyaddress()
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
return ListReceived(pwallet, request.params, false); return ListReceived(*pwallet, request.params, false);
}, },
}; };
} }
@ -1270,9 +1257,8 @@ static RPCHelpMan listreceivedbylabel()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -1280,7 +1266,7 @@ static RPCHelpMan listreceivedbylabel()
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
return ListReceived(pwallet, request.params, true); return ListReceived(*pwallet, request.params, true);
}, },
}; };
} }
@ -1303,7 +1289,7 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
* @param filter_ismine The "is mine" filter flags. * @param filter_ismine The "is mine" filter flags.
* @param filter_label Optional label string to filter incoming transactions. * @param filter_label Optional label string to filter incoming transactions.
*/ */
static void ListTransactions(const CWallet* const pwallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter_ismine, const std::string* filter_label) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter_ismine, const std::string* filter_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{ {
CAmount nFee; CAmount nFee;
std::list<COutputEntry> listReceived; std::list<COutputEntry> listReceived;
@ -1319,20 +1305,20 @@ static void ListTransactions(const CWallet* const pwallet, const CWalletTx& wtx,
for (const COutputEntry& s : listSent) for (const COutputEntry& s : listSent)
{ {
UniValue entry(UniValue::VOBJ); UniValue entry(UniValue::VOBJ);
if (involvesWatchonly || (pwallet->IsMine(s.destination) & ISMINE_WATCH_ONLY)) { if (involvesWatchonly || (wallet.IsMine(s.destination) & ISMINE_WATCH_ONLY)) {
entry.pushKV("involvesWatchonly", true); entry.pushKV("involvesWatchonly", true);
} }
MaybePushAddress(entry, s.destination); MaybePushAddress(entry, s.destination);
entry.pushKV("category", "send"); entry.pushKV("category", "send");
entry.pushKV("amount", ValueFromAmount(-s.amount)); entry.pushKV("amount", ValueFromAmount(-s.amount));
const auto* address_book_entry = pwallet->FindAddressBookEntry(s.destination); const auto* address_book_entry = wallet.FindAddressBookEntry(s.destination);
if (address_book_entry) { if (address_book_entry) {
entry.pushKV("label", address_book_entry->GetLabel()); entry.pushKV("label", address_book_entry->GetLabel());
} }
entry.pushKV("vout", s.vout); entry.pushKV("vout", s.vout);
entry.pushKV("fee", ValueFromAmount(-nFee)); entry.pushKV("fee", ValueFromAmount(-nFee));
if (fLong) if (fLong)
WalletTxToJSON(pwallet->chain(), wtx, entry); WalletTxToJSON(wallet.chain(), wtx, entry);
entry.pushKV("abandoned", wtx.isAbandoned()); entry.pushKV("abandoned", wtx.isAbandoned());
ret.push_back(entry); ret.push_back(entry);
} }
@ -1343,7 +1329,7 @@ static void ListTransactions(const CWallet* const pwallet, const CWalletTx& wtx,
for (const COutputEntry& r : listReceived) for (const COutputEntry& r : listReceived)
{ {
std::string label; std::string label;
const auto* address_book_entry = pwallet->FindAddressBookEntry(r.destination); const auto* address_book_entry = wallet.FindAddressBookEntry(r.destination);
if (address_book_entry) { if (address_book_entry) {
label = address_book_entry->GetLabel(); label = address_book_entry->GetLabel();
} }
@ -1351,7 +1337,7 @@ static void ListTransactions(const CWallet* const pwallet, const CWalletTx& wtx,
continue; continue;
} }
UniValue entry(UniValue::VOBJ); UniValue entry(UniValue::VOBJ);
if (involvesWatchonly || (pwallet->IsMine(r.destination) & ISMINE_WATCH_ONLY)) { if (involvesWatchonly || (wallet.IsMine(r.destination) & ISMINE_WATCH_ONLY)) {
entry.pushKV("involvesWatchonly", true); entry.pushKV("involvesWatchonly", true);
} }
MaybePushAddress(entry, r.destination); MaybePushAddress(entry, r.destination);
@ -1374,7 +1360,7 @@ static void ListTransactions(const CWallet* const pwallet, const CWalletTx& wtx,
} }
entry.pushKV("vout", r.vout); entry.pushKV("vout", r.vout);
if (fLong) if (fLong)
WalletTxToJSON(pwallet->chain(), wtx, entry); WalletTxToJSON(wallet.chain(), wtx, entry);
ret.push_back(entry); ret.push_back(entry);
} }
} }
@ -1451,9 +1437,8 @@ static RPCHelpMan listtransactions()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -1494,7 +1479,7 @@ static RPCHelpMan listtransactions()
for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{ {
CWalletTx *const pwtx = (*it).second; CWalletTx *const pwtx = (*it).second;
ListTransactions(pwallet, *pwtx, 0, true, ret, filter, filter_label); ListTransactions(*pwallet, *pwtx, 0, true, ret, filter, filter_label);
if ((int)ret.size() >= (nCount+nFrom)) break; if ((int)ret.size() >= (nCount+nFrom)) break;
} }
} }
@ -1616,7 +1601,7 @@ static RPCHelpMan listsinceblock()
const CWalletTx& tx = pairWtx.second; const CWalletTx& tx = pairWtx.second;
if (depth == -1 || abs(tx.GetDepthInMainChain()) < depth) { if (depth == -1 || abs(tx.GetDepthInMainChain()) < depth) {
ListTransactions(&wallet, tx, 0, true, transactions, filter, nullptr /* filter_label */); ListTransactions(wallet, tx, 0, true, transactions, filter, nullptr /* filter_label */);
} }
} }
@ -1633,7 +1618,7 @@ static RPCHelpMan listsinceblock()
if (it != wallet.mapWallet.end()) { if (it != wallet.mapWallet.end()) {
// We want all transactions regardless of confirmation count to appear here, // We want all transactions regardless of confirmation count to appear here,
// even negative confirmation ones, hence the big negative. // even negative confirmation ones, hence the big negative.
ListTransactions(&wallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */); ListTransactions(wallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */);
} }
} }
blockId = block.hashPrevBlock; blockId = block.hashPrevBlock;
@ -1710,9 +1695,8 @@ static RPCHelpMan gettransaction()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -1749,7 +1733,7 @@ static RPCHelpMan gettransaction()
WalletTxToJSON(pwallet->chain(), wtx, entry); WalletTxToJSON(pwallet->chain(), wtx, entry);
UniValue details(UniValue::VARR); UniValue details(UniValue::VARR);
ListTransactions(pwallet, wtx, 0, false, details, filter, nullptr /* filter_label */); ListTransactions(*pwallet, wtx, 0, false, details, filter, nullptr /* filter_label */);
entry.pushKV("details", details); entry.pushKV("details", details);
std::string strHex = EncodeHexTx(*wtx.tx, pwallet->chain().rpcSerializationFlags()); std::string strHex = EncodeHexTx(*wtx.tx, pwallet->chain().rpcSerializationFlags());
@ -1784,9 +1768,8 @@ static RPCHelpMan abandontransaction()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -1823,9 +1806,8 @@ static RPCHelpMan backupwallet()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -1859,9 +1841,8 @@ static RPCHelpMan keypoolrefill()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
if (pwallet->IsLegacy() && pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { if (pwallet->IsLegacy() && pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet"); throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
@ -1877,7 +1858,7 @@ static RPCHelpMan keypoolrefill()
kpSize = (unsigned int)request.params[0].get_int(); kpSize = (unsigned int)request.params[0].get_int();
} }
EnsureWalletIsUnlocked(pwallet); EnsureWalletIsUnlocked(*pwallet);
pwallet->TopUpKeyPool(kpSize); pwallet->TopUpKeyPool(kpSize);
if (pwallet->GetKeyPoolSize() < kpSize) { if (pwallet->GetKeyPoolSize() < kpSize) {
@ -2001,9 +1982,8 @@ static RPCHelpMan walletpassphrasechange()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
@ -2055,9 +2035,8 @@ static RPCHelpMan walletlock()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
@ -2100,9 +2079,8 @@ static RPCHelpMan encryptwallet()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
@ -2174,9 +2152,8 @@ static RPCHelpMan lockunspent()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -2289,9 +2266,8 @@ static RPCHelpMan listlockunspent()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
@ -2330,9 +2306,8 @@ static RPCHelpMan settxfee()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
@ -2460,9 +2435,8 @@ static RPCHelpMan getwalletinfo()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
@ -2672,9 +2646,8 @@ static RPCHelpMan setwalletflag()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
std::string flag_str = request.params[0].get_str(); std::string flag_str = request.params[0].get_str();
bool value = request.params[1].isNull() || request.params[1].get_bool(); bool value = request.params[1].isNull() || request.params[1].get_bool();
@ -2916,9 +2889,8 @@ static RPCHelpMan listunspent()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
int nMinDepth = 1; int nMinDepth = 1;
if (!request.params[0].isNull()) { if (!request.params[0].isNull()) {
@ -3080,11 +3052,11 @@ static RPCHelpMan listunspent()
}; };
} }
void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& fee_out, int& change_position, const UniValue& options, CCoinControl& coinControl, bool override_min_fee) void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out, int& change_position, const UniValue& options, CCoinControl& coinControl, bool override_min_fee)
{ {
// Make sure the results are valid at least up to the most recent block // Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now // the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain(); wallet.BlockUntilSyncedToCurrentChain();
change_position = -1; change_position = -1;
bool lockUnspents = false; bool lockUnspents = false;
@ -3155,7 +3127,7 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
} }
const UniValue include_watching_option = options.exists("include_watching") ? options["include_watching"] : options["includeWatching"]; const UniValue include_watching_option = options.exists("include_watching") ? options["include_watching"] : options["includeWatching"];
coinControl.fAllowWatchOnly = ParseIncludeWatchonly(include_watching_option, *pwallet); coinControl.fAllowWatchOnly = ParseIncludeWatchonly(include_watching_option, wallet);
if (options.exists("lockUnspents") || options.exists("lock_unspents")) { if (options.exists("lockUnspents") || options.exists("lock_unspents")) {
lockUnspents = (options.exists("lock_unspents") ? options["lock_unspents"] : options["lockUnspents"]).get_bool(); lockUnspents = (options.exists("lock_unspents") ? options["lock_unspents"] : options["lockUnspents"]).get_bool();
@ -3181,11 +3153,11 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
if (options.exists("replaceable")) { if (options.exists("replaceable")) {
coinControl.m_signal_bip125_rbf = options["replaceable"].get_bool(); coinControl.m_signal_bip125_rbf = options["replaceable"].get_bool();
} }
SetFeeEstimateMode(*pwallet, coinControl, options["conf_target"], options["estimate_mode"], options["fee_rate"], override_min_fee); SetFeeEstimateMode(wallet, coinControl, options["conf_target"], options["estimate_mode"], options["fee_rate"], override_min_fee);
} }
} else { } else {
// if options is null and not a bool // if options is null and not a bool
coinControl.fAllowWatchOnly = ParseIncludeWatchonly(NullUniValue, *pwallet); coinControl.fAllowWatchOnly = ParseIncludeWatchonly(NullUniValue, wallet);
} }
if (tx.vout.size() == 0) if (tx.vout.size() == 0)
@ -3207,7 +3179,7 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
bilingual_str error; bilingual_str error;
if (!pwallet->FundTransaction(tx, fee_out, change_position, error, lockUnspents, setSubtractFeeFromOutputs, coinControl)) { if (!wallet.FundTransaction(tx, fee_out, change_position, error, lockUnspents, setSubtractFeeFromOutputs, coinControl)) {
throw JSONRPCError(RPC_WALLET_ERROR, error.original); throw JSONRPCError(RPC_WALLET_ERROR, error.original);
} }
} }
@ -3283,9 +3255,8 @@ static RPCHelpMan fundrawtransaction()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType(), UniValue::VBOOL}); RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType(), UniValue::VBOOL});
@ -3302,7 +3273,7 @@ static RPCHelpMan fundrawtransaction()
CCoinControl coin_control; CCoinControl coin_control;
// Automatically select (additional) coins. Can be overridden by options.add_inputs. // Automatically select (additional) coins. Can be overridden by options.add_inputs.
coin_control.m_add_inputs = true; coin_control.m_add_inputs = true;
FundTransaction(pwallet, tx, fee, change_position, request.params[1], coin_control, /* override_min_fee */ true); FundTransaction(*pwallet, tx, fee, change_position, request.params[1], coin_control, /* override_min_fee */ true);
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
result.pushKV("hex", EncodeHexTx(CTransaction(tx))); result.pushKV("hex", EncodeHexTx(CTransaction(tx)));
@ -3369,9 +3340,8 @@ RPCHelpMan signrawtransactionwithwallet()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VSTR}, true); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VSTR}, true);
@ -3382,7 +3352,7 @@ RPCHelpMan signrawtransactionwithwallet()
// Sign the transaction // Sign the transaction
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet); EnsureWalletIsUnlocked(*pwallet);
// Fetch previous transactions (inputs): // Fetch previous transactions (inputs):
std::map<COutPoint, Coin> coins; std::map<COutPoint, Coin> coins;
@ -3469,9 +3439,8 @@ static RPCHelpMan bumpfee_helper(std::string method_name)
}, },
[want_psbt](const RPCHelpMan& self, const JSONRPCRequest& request) mutable -> UniValue [want_psbt](const RPCHelpMan& self, const JSONRPCRequest& request) mutable -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !want_psbt) { if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !want_psbt) {
throw JSONRPCError(RPC_WALLET_ERROR, "bumpfee is not available with wallets that have private keys disabled. Use psbtbumpfee instead."); throw JSONRPCError(RPC_WALLET_ERROR, "bumpfee is not available with wallets that have private keys disabled. Use psbtbumpfee instead.");
@ -3514,7 +3483,8 @@ static RPCHelpMan bumpfee_helper(std::string method_name)
pwallet->BlockUntilSyncedToCurrentChain(); pwallet->BlockUntilSyncedToCurrentChain();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
EnsureWalletIsUnlocked(*pwallet);
std::vector<bilingual_str> errors; std::vector<bilingual_str> errors;
@ -3608,9 +3578,8 @@ static RPCHelpMan rescanblockchain()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
WalletRescanReserver reserver(*pwallet); WalletRescanReserver reserver(*pwallet);
if (!reserver.reserve()) { if (!reserver.reserve()) {
@ -3759,15 +3728,13 @@ public:
UniValue operator()(const WitnessUnknown& id) const { return UniValue(UniValue::VOBJ); } UniValue operator()(const WitnessUnknown& id) const { return UniValue(UniValue::VOBJ); }
}; };
static UniValue DescribeWalletAddress(const CWallet* const pwallet, const CTxDestination& dest) static UniValue DescribeWalletAddress(const CWallet& wallet, const CTxDestination& dest)
{ {
UniValue ret(UniValue::VOBJ); UniValue ret(UniValue::VOBJ);
UniValue detail = DescribeAddress(dest); UniValue detail = DescribeAddress(dest);
CScript script = GetScriptForDestination(dest); CScript script = GetScriptForDestination(dest);
std::unique_ptr<SigningProvider> provider = nullptr; std::unique_ptr<SigningProvider> provider = nullptr;
if (pwallet) { provider = wallet.GetSolvingProvider(script);
provider = pwallet->GetSolvingProvider(script);
}
ret.pushKVs(detail); ret.pushKVs(detail);
ret.pushKVs(std::visit(DescribeWalletAddressVisitor(provider.get()), dest)); ret.pushKVs(std::visit(DescribeWalletAddressVisitor(provider.get()), dest));
return ret; return ret;
@ -3840,9 +3807,8 @@ RPCHelpMan getaddressinfo()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
@ -3887,7 +3853,7 @@ RPCHelpMan getaddressinfo()
ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY)); ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
UniValue detail = DescribeWalletAddress(pwallet, dest); UniValue detail = DescribeWalletAddress(*pwallet, dest);
ret.pushKVs(detail); ret.pushKVs(detail);
ret.pushKV("ischange", pwallet->IsChange(scriptPubKey)); ret.pushKV("ischange", pwallet->IsChange(scriptPubKey));
@ -3943,9 +3909,8 @@ static RPCHelpMan getaddressesbylabel()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
@ -4005,9 +3970,8 @@ static RPCHelpMan listlabels()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
@ -4130,9 +4094,8 @@ static RPCHelpMan send()
}, true }, true
); );
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
UniValue options{request.params[4].isNull() ? UniValue::VOBJ : request.params[4]}; UniValue options{request.params[4].isNull() ? UniValue::VOBJ : request.params[4]};
if (options.exists("conf_target") || options.exists("estimate_mode")) { if (options.exists("conf_target") || options.exists("estimate_mode")) {
@ -4185,7 +4148,7 @@ static RPCHelpMan send()
// Automatically select coins, unless at least one is manually selected. Can // Automatically select coins, unless at least one is manually selected. Can
// be overridden by options.add_inputs. // be overridden by options.add_inputs.
coin_control.m_add_inputs = rawTx.vin.size() == 0; coin_control.m_add_inputs = rawTx.vin.size() == 0;
FundTransaction(pwallet, rawTx, fee, change_position, options, coin_control, /* override_min_fee */ false); FundTransaction(*pwallet, rawTx, fee, change_position, options, coin_control, /* override_min_fee */ false);
bool add_to_wallet = true; bool add_to_wallet = true;
if (options.exists("add_to_wallet")) { if (options.exists("add_to_wallet")) {
@ -4258,9 +4221,8 @@ static RPCHelpMan sethdseed()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet, true); LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet, true);
@ -4275,7 +4237,7 @@ static RPCHelpMan sethdseed()
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set an HD seed on a non-HD wallet. Use the upgradewallet RPC in order to upgrade a non-HD wallet to HD"); throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set an HD seed on a non-HD wallet. Use the upgradewallet RPC in order to upgrade a non-HD wallet to HD");
} }
EnsureWalletIsUnlocked(pwallet); EnsureWalletIsUnlocked(*pwallet);
bool flush_key_pool = true; bool flush_key_pool = true;
if (!request.params[0].isNull()) { if (!request.params[0].isNull()) {
@ -4336,9 +4298,8 @@ static RPCHelpMan walletprocesspsbt()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
const CWallet* const pwallet = wallet.get();
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VSTR}); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VSTR});
@ -4448,9 +4409,8 @@ static RPCHelpMan walletcreatefundedpsbt()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
RPCTypeCheck(request.params, { RPCTypeCheck(request.params, {
UniValue::VARR, UniValue::VARR,
@ -4474,7 +4434,7 @@ static RPCHelpMan walletcreatefundedpsbt()
// Automatically select coins, unless at least one is manually selected. Can // Automatically select coins, unless at least one is manually selected. Can
// be overridden by options.add_inputs. // be overridden by options.add_inputs.
coin_control.m_add_inputs = rawTx.vin.size() == 0; coin_control.m_add_inputs = rawTx.vin.size() == 0;
FundTransaction(pwallet, rawTx, fee, change_position, request.params[3], coin_control, /* override_min_fee */ true); FundTransaction(*pwallet, rawTx, fee, change_position, request.params[3], coin_control, /* override_min_fee */ true);
// Make a blank psbt // Make a blank psbt
PartiallySignedTransaction psbtx(rawTx); PartiallySignedTransaction psbtx(rawTx);
@ -4524,13 +4484,12 @@ static RPCHelpMan upgradewallet()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!wallet) return NullUniValue; if (!pwallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
RPCTypeCheck(request.params, {UniValue::VNUM}, true); RPCTypeCheck(request.params, {UniValue::VNUM}, true);
EnsureWalletIsUnlocked(pwallet); EnsureWalletIsUnlocked(*pwallet);
int version = 0; int version = 0;
if (!request.params[0].isNull()) { if (!request.params[0].isNull()) {

View file

@ -30,7 +30,7 @@ Span<const CRPCCommand> GetWalletRPCCommands();
*/ */
std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request); std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request);
void EnsureWalletIsUnlocked(const CWallet*); void EnsureWalletIsUnlocked(const CWallet&);
WalletContext& EnsureWalletContext(const util::Ref& context); WalletContext& EnsureWalletContext(const util::Ref& context);
LegacyScriptPubKeyMan& EnsureLegacyScriptPubKeyMan(CWallet& wallet, bool also_create = false); LegacyScriptPubKeyMan& EnsureLegacyScriptPubKeyMan(CWallet& wallet, bool also_create = false);