Skip to content

Commit 6a16732

Browse files
committed
Merge bitcoin/bitcoin#27279: Add "warnings", deprecate "warning" in {create,load,unload,restore}wallet
7ccdd74 test: fix importmulti/importdescriptors assertion (Jon Atack) 19d888c rpc: move WALLET_FLAG_CAVEATS to the compilation unit of its caller (Jon Atack) 01df011 doc: release note for wallet RPCs "warning" field deprecation (Jon Atack) 9ea8b37 test: createwallet "warning" field deprecation test (Jon Atack) 645d7f7 rpc: deprecate "warning" field in {create,load,unload,restore}wallet (Jon Atack) 2f4a926 test: add test coverage for "warnings" field in createwallet (Jon Atack) 4a1e479 rpc: add "warnings" field to RPCs {create,load,unload,restore}wallet (Jon Atack) 079d8cd rpc: extract wallet "warnings" fields to a util helper (Jon Atack) f73782a doc: fix/improve warning helps in {create,load,unload,restore}wallet (Jon Atack) Pull request description: Based on discussion and concept ACKed in #27138, add a `warnings` field to RPCs createwallet, loadwallet, unloadwallet, and restorewallet as a JSON array of strings to replace the `warning` string field in these 4 RPCs. The idea is to more gracefully handle multiple warning messages and for consistency with other wallet RPCs. Then, deprecate the latter fields, which represent all the remaining RPC `warning` fields. The first commit bitcoin/bitcoin@f73782a implements bitcoin/bitcoin#27138 (comment) as an alternative to #27138. One of those two could potentially be backported to our currently supported releases. ACKs for top commit: achow101: ACK 7ccdd74 1440000bytes: utACK bitcoin/bitcoin@7ccdd74 vasild: ACK 7ccdd74 pinheadmz: re-ACK 7ccdd74 Tree-SHA512: 314e0a4c41fa383d95e2817bfacf359d449e460529d235c3eb902851e2f4eacbabe646d9a5a4beabc4964cdfabf6397ed8301366a58d344a2f787f83b75e9d64
2 parents 7f4ab67 + 7ccdd74 commit 6a16732

File tree

11 files changed

+125
-28
lines changed

11 files changed

+125
-28
lines changed

doc/release-notes-27279.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Wallet
2+
------
3+
4+
- In the createwallet, loadwallet, unloadwallet, and restorewallet RPCs, the
5+
"warning" string field is deprecated in favor of a "warnings" field that
6+
returns a JSON array of strings to better handle multiple warning messages and
7+
for consistency with other wallet RPCs. The "warning" field will be fully
8+
removed from these RPCs in v26. It can be temporarily re-enabled during the
9+
deprecation period by launching bitcoind with the configuration option
10+
`-deprecatedrpc=walletwarningfield`. (#27279)

src/rpc/output_script.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ static RPCHelpMan createmultisig()
162162
// Only warns if the user has explicitly chosen an address type we cannot generate
163163
warnings.push_back("Unable to make chosen address type, please ensure no uncompressed public keys are present.");
164164
}
165-
if (!warnings.empty()) result.pushKV("warnings", warnings);
165+
PushWarnings(warnings, result);
166166

167167
return result;
168168
},

src/rpc/util.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,3 +1174,26 @@ UniValue GetServicesNames(ServiceFlags services)
11741174

11751175
return servicesNames;
11761176
}
1177+
1178+
/** Convert a vector of bilingual strings to a UniValue::VARR containing their original untranslated values. */
1179+
[[nodiscard]] static UniValue BilingualStringsToUniValue(const std::vector<bilingual_str>& bilingual_strings)
1180+
{
1181+
CHECK_NONFATAL(!bilingual_strings.empty());
1182+
UniValue result{UniValue::VARR};
1183+
for (const auto& s : bilingual_strings) {
1184+
result.push_back(s.original);
1185+
}
1186+
return result;
1187+
}
1188+
1189+
void PushWarnings(const UniValue& warnings, UniValue& obj)
1190+
{
1191+
if (warnings.empty()) return;
1192+
obj.pushKV("warnings", warnings);
1193+
}
1194+
1195+
void PushWarnings(const std::vector<bilingual_str>& warnings, UniValue& obj)
1196+
{
1197+
if (warnings.empty()) return;
1198+
obj.pushKV("warnings", BilingualStringsToUniValue(warnings));
1199+
}

src/rpc/util.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,4 +381,13 @@ class RPCHelpMan
381381
const RPCExamples m_examples;
382382
};
383383

384+
/**
385+
* Push warning messages to an RPC "warnings" field as a JSON array of strings.
386+
*
387+
* @param[in] warnings Warning messages to push.
388+
* @param[out] obj UniValue object to push the warnings array object to.
389+
*/
390+
void PushWarnings(const UniValue& warnings, UniValue& obj);
391+
void PushWarnings(const std::vector<bilingual_str>& warnings, UniValue& obj);
392+
384393
#endif // BITCOIN_RPC_UTIL_H

src/wallet/rpc/addresses.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ RPCHelpMan addmultisigaddress()
300300
// Only warns if the user has explicitly chosen an address type we cannot generate
301301
warnings.push_back("Unable to make chosen address type, please ensure no uncompressed public keys are present.");
302302
}
303-
if (!warnings.empty()) result.pushKV("warnings", warnings);
303+
PushWarnings(warnings, result);
304304

305305
return result;
306306
},

src/wallet/rpc/backup.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,7 +1225,7 @@ static UniValue ProcessImport(CWallet& wallet, const UniValue& data, const int64
12251225

12261226
result.pushKV("error", JSONRPCError(RPC_MISC_ERROR, "Missing required fields"));
12271227
}
1228-
if (warnings.size()) result.pushKV("warnings", warnings);
1228+
PushWarnings(warnings, result);
12291229
return result;
12301230
}
12311231

@@ -1579,7 +1579,7 @@ static UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, c
15791579
result.pushKV("success", UniValue(false));
15801580
result.pushKV("error", e);
15811581
}
1582-
if (warnings.size()) result.pushKV("warnings", warnings);
1582+
PushWarnings(warnings, result);
15831583
return result;
15841584
}
15851585

@@ -1903,7 +1903,11 @@ RPCHelpMan restorewallet()
19031903
RPCResult::Type::OBJ, "", "",
19041904
{
19051905
{RPCResult::Type::STR, "name", "The wallet name if restored successfully."},
1906-
{RPCResult::Type::STR, "warning", "Warning message if wallet was not loaded cleanly."},
1906+
{RPCResult::Type::STR, "warning", /*optional=*/true, "Warning messages, if any, related to restoring the wallet. Multiple messages will be delimited by newlines. (DEPRECATED, returned only if config option -deprecatedrpc=walletwarningfield is passed.)"},
1907+
{RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to restoring the wallet.",
1908+
{
1909+
{RPCResult::Type::STR, "", ""},
1910+
}},
19071911
}
19081912
},
19091913
RPCExamples{
@@ -1933,7 +1937,10 @@ RPCHelpMan restorewallet()
19331937

19341938
UniValue obj(UniValue::VOBJ);
19351939
obj.pushKV("name", wallet->GetName());
1936-
obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
1940+
if (wallet->chain().rpcEnableDeprecated("walletwarningfield")) {
1941+
obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
1942+
}
1943+
PushWarnings(warnings, obj);
19371944

19381945
return obj;
19391946

src/wallet/rpc/wallet.cpp

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,22 @@
1313
#include <wallet/rpc/wallet.h>
1414
#include <wallet/rpc/util.h>
1515
#include <wallet/wallet.h>
16+
#include <wallet/walletutil.h>
1617

1718
#include <optional>
1819

1920
#include <univalue.h>
2021

2122

2223
namespace wallet {
24+
25+
static const std::map<uint64_t, std::string> WALLET_FLAG_CAVEATS{
26+
{WALLET_FLAG_AVOID_REUSE,
27+
"You need to rescan the blockchain in order to correctly mark used "
28+
"destinations in the past. Until this is done, some destinations may "
29+
"be considered unused, even if the opposite is the case."},
30+
};
31+
2332
/** Checks if a CKey is in the given CWallet compressed or otherwise*/
2433
bool HaveKey(const SigningProvider& wallet, const CKey& key)
2534
{
@@ -207,7 +216,11 @@ static RPCHelpMan loadwallet()
207216
RPCResult::Type::OBJ, "", "",
208217
{
209218
{RPCResult::Type::STR, "name", "The wallet name if loaded successfully."},
210-
{RPCResult::Type::STR, "warning", "Warning message if wallet was not loaded cleanly."},
219+
{RPCResult::Type::STR, "warning", /*optional=*/true, "Warning messages, if any, related to loading the wallet. Multiple messages will be delimited by newlines. (DEPRECATED, returned only if config option -deprecatedrpc=walletwarningfield is passed.)"},
220+
{RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to loading the wallet.",
221+
{
222+
{RPCResult::Type::STR, "", ""},
223+
}},
211224
}
212225
},
213226
RPCExamples{
@@ -240,7 +253,10 @@ static RPCHelpMan loadwallet()
240253

241254
UniValue obj(UniValue::VOBJ);
242255
obj.pushKV("name", wallet->GetName());
243-
obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
256+
if (wallet->chain().rpcEnableDeprecated("walletwarningfield")) {
257+
obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
258+
}
259+
PushWarnings(warnings, obj);
244260

245261
return obj;
246262
},
@@ -335,7 +351,11 @@ static RPCHelpMan createwallet()
335351
RPCResult::Type::OBJ, "", "",
336352
{
337353
{RPCResult::Type::STR, "name", "The wallet name if created successfully. If the wallet was created using a full path, the wallet_name will be the full path."},
338-
{RPCResult::Type::STR, "warning", "Warning message if wallet was not loaded cleanly."},
354+
{RPCResult::Type::STR, "warning", /*optional=*/true, "Warning messages, if any, related to creating the wallet. Multiple messages will be delimited by newlines. (DEPRECATED, returned only if config option -deprecatedrpc=walletwarningfield is passed.)"},
355+
{RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to creating the wallet.",
356+
{
357+
{RPCResult::Type::STR, "", ""},
358+
}},
339359
}
340360
},
341361
RPCExamples{
@@ -405,7 +425,10 @@ static RPCHelpMan createwallet()
405425

406426
UniValue obj(UniValue::VOBJ);
407427
obj.pushKV("name", wallet->GetName());
408-
obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
428+
if (wallet->chain().rpcEnableDeprecated("walletwarningfield")) {
429+
obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
430+
}
431+
PushWarnings(warnings, obj);
409432

410433
return obj;
411434
},
@@ -422,7 +445,11 @@ static RPCHelpMan unloadwallet()
422445
{"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
423446
},
424447
RPCResult{RPCResult::Type::OBJ, "", "", {
425-
{RPCResult::Type::STR, "warning", "Warning message if wallet was not unloaded cleanly."},
448+
{RPCResult::Type::STR, "warning", /*optional=*/true, "Warning messages, if any, related to unloading the wallet. Multiple messages will be delimited by newlines. (DEPRECATED, returned only if config option -deprecatedrpc=walletwarningfield is passed.)"},
449+
{RPCResult::Type::ARR, "warnings", /*optional=*/true, "Warning messages, if any, related to unloading the wallet.",
450+
{
451+
{RPCResult::Type::STR, "", ""},
452+
}},
426453
}},
427454
RPCExamples{
428455
HelpExampleCli("unloadwallet", "wallet_name")
@@ -460,11 +487,13 @@ static RPCHelpMan unloadwallet()
460487
throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
461488
}
462489
}
490+
UniValue result(UniValue::VOBJ);
491+
if (wallet->chain().rpcEnableDeprecated("walletwarningfield")) {
492+
result.pushKV("warning", Join(warnings, Untranslated("\n")).original);
493+
}
494+
PushWarnings(warnings, result);
463495

464496
UnloadWallet(std::move(wallet));
465-
466-
UniValue result(UniValue::VOBJ);
467-
result.pushKV("warning", Join(warnings, Untranslated("\n")).original);
468497
return result;
469498
},
470499
};

src/wallet/wallet.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,6 @@
5252
using interfaces::FoundBlock;
5353

5454
namespace wallet {
55-
const std::map<uint64_t,std::string> WALLET_FLAG_CAVEATS{
56-
{WALLET_FLAG_AVOID_REUSE,
57-
"You need to rescan the blockchain in order to correctly mark used "
58-
"destinations in the past. Until this is done, some destinations may "
59-
"be considered unused, even if the opposite is the case."
60-
},
61-
};
6255

6356
bool AddWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
6457
{

src/wallet/wallet.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,6 @@ static const std::map<std::string,WalletFlags> WALLET_FLAG_MAP{
146146
{"external_signer", WALLET_FLAG_EXTERNAL_SIGNER}
147147
};
148148

149-
extern const std::map<uint64_t,std::string> WALLET_FLAG_CAVEATS;
150-
151149
/** A wrapper to reserve an address from a wallet
152150
*
153151
* ReserveDestination is used to reserve an address.

test/functional/wallet_backwards_compatibility.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,12 @@ def run_test(self):
265265
)
266266
load_res = node_master.loadwallet("u1_v16")
267267
# Make sure this wallet opens without warnings. See https://github.com/bitcoin/bitcoin/pull/19054
268-
assert_equal(load_res['warning'], '')
268+
if int(node_master.getnetworkinfo()["version"]) >= 249900:
269+
# loadwallet#warnings (added in v25) -- only present if there is a warning
270+
assert "warnings" not in load_res
271+
else:
272+
# loadwallet#warning (deprecated in v25) -- always present, but empty string if no warning
273+
assert_equal(load_res["warning"], '')
269274
wallet = node_master.get_wallet_rpc("u1_v16")
270275
info = wallet.getaddressinfo(v16_addr)
271276
descriptor = f"wpkh([{info['hdmasterfingerprint']}{hdkeypath[1:]}]{v16_pubkey})"

0 commit comments

Comments
 (0)