Skip to content

Commit 99d56e3

Browse files
committed
wallet: fix and improve upgradewallet result responses
1 parent 2498b04 commit 99d56e3

File tree

2 files changed

+51
-32
lines changed

2 files changed

+51
-32
lines changed

src/wallet/rpcwallet.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4214,7 +4214,7 @@ static RPCHelpMan sethdseed()
42144214

42154215
// Do not do anything to non-HD wallets
42164216
if (!pwallet->CanSupportFeature(FEATURE_HD)) {
4217-
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed on a non-HD wallet. Use the upgradewallet RPC in order to upgrade a non-HD wallet to HD");
4217+
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");
42184218
}
42194219

42204220
EnsureWalletIsUnlocked(pwallet);
@@ -4445,14 +4445,18 @@ static RPCHelpMan walletcreatefundedpsbt()
44454445
static RPCHelpMan upgradewallet()
44464446
{
44474447
return RPCHelpMan{"upgradewallet",
4448-
"\nUpgrade the wallet. Upgrades to the latest version if no version number is specified\n"
4448+
"\nUpgrade the wallet. Upgrades to the latest version if no version number is specified.\n"
44494449
"New keys may be generated and a new wallet backup will need to be made.",
44504450
{
4451-
{"version", RPCArg::Type::NUM, /* default */ strprintf("%d", FEATURE_LATEST), "The version number to upgrade to. Default is the latest wallet version"}
4451+
{"version", RPCArg::Type::NUM, /* default */ strprintf("%d", FEATURE_LATEST), "The version number to upgrade to. Default is the latest wallet version."}
44524452
},
44534453
RPCResult{
44544454
RPCResult::Type::OBJ, "", "",
44554455
{
4456+
{RPCResult::Type::STR, "wallet_name", "Name of wallet this operation was performed on"},
4457+
{RPCResult::Type::NUM, "previous_version", "Version of wallet before this operation"},
4458+
{RPCResult::Type::NUM, "current_version", "Version of wallet after this operation"},
4459+
{RPCResult::Type::STR, "result", /* optional */ true, "Description of result, if no error"},
44564460
{RPCResult::Type::STR, "error", /* optional */ true, "Error message (if there is one)"}
44574461
},
44584462
},
@@ -4475,10 +4479,26 @@ static RPCHelpMan upgradewallet()
44754479
version = request.params[0].get_int();
44764480
}
44774481
bilingual_str error;
4478-
if (!pwallet->UpgradeWallet(version, error)) {
4482+
const int previous_version{pwallet->GetVersion()};
4483+
const bool wallet_upgraded{pwallet->UpgradeWallet(version, error)};
4484+
const int current_version{pwallet->GetVersion()};
4485+
std::string result;
4486+
4487+
if (!wallet_upgraded) {
44794488
throw JSONRPCError(RPC_WALLET_ERROR, error.original);
4489+
} else if (previous_version == current_version) {
4490+
result = "Already at latest version. Wallet version unchanged.";
4491+
} else {
4492+
result = strprintf("Wallet upgraded successfully from version %i to version %i.", previous_version, current_version);
44804493
}
4494+
44814495
UniValue obj(UniValue::VOBJ);
4496+
obj.pushKV("wallet_name", pwallet->GetName());
4497+
obj.pushKV("previous_version", previous_version);
4498+
obj.pushKV("current_version", current_version);
4499+
if (!result.empty()) {
4500+
obj.pushKV("result", result);
4501+
}
44824502
if (!error.empty()) {
44834503
obj.pushKV("error", error.original);
44844504
}

test/functional/wallet_upgradewallet.py

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
from test_framework.test_framework import BitcoinTestFramework
2323
from test_framework.util import (
2424
assert_equal,
25-
assert_greater_than,
2625
assert_is_hex_string,
2726
assert_raises_rpc_error,
2827
sha256sum_file,
@@ -92,6 +91,20 @@ def dumb_sync_blocks(self):
9291
v16_3_node.submitblock(b)
9392
assert_equal(v16_3_node.getblockcount(), to_height)
9493

94+
def test_upgradewallet(self, wallet, previous_version, requested_version=None, expected_version=None):
95+
unchanged = expected_version == previous_version
96+
new_version = previous_version if unchanged else expected_version if expected_version else requested_version
97+
assert_equal(wallet.getwalletinfo()["walletversion"], previous_version)
98+
assert_equal(wallet.upgradewallet(requested_version),
99+
{
100+
"wallet_name": "",
101+
"previous_version": previous_version,
102+
"current_version": new_version,
103+
"result": "Already at latest version. Wallet version unchanged." if unchanged else "Wallet upgraded successfully from version {} to version {}.".format(previous_version, new_version),
104+
}
105+
)
106+
assert_equal(wallet.getwalletinfo()["walletversion"], new_version)
107+
95108
def run_test(self):
96109
self.nodes[0].generatetoaddress(101, self.nodes[0].getnewaddress())
97110
self.dumb_sync_blocks()
@@ -158,40 +171,29 @@ def copy_split_hd():
158171
self.restart_node(0)
159172
copy_v16()
160173
wallet = node_master.get_wallet_rpc(self.default_wallet_name)
161-
old_version = wallet.getwalletinfo()["walletversion"]
162-
163-
# calling upgradewallet without version arguments
164-
# should return nothing if successful
165-
assert_equal(wallet.upgradewallet(), {})
166-
new_version = wallet.getwalletinfo()["walletversion"]
167-
# upgraded wallet version should be greater than older one
168-
assert_greater_than(new_version, old_version)
174+
self.log.info("Test upgradewallet without a version argument")
175+
self.test_upgradewallet(wallet, previous_version=159900, expected_version=169900)
169176
# wallet should still contain the same balance
170177
assert_equal(wallet.getbalance(), v16_3_balance)
171178

172179
copy_non_hd()
173180
wallet = node_master.get_wallet_rpc(self.default_wallet_name)
174181
# should have no master key hash before conversion
175182
assert_equal('hdseedid' in wallet.getwalletinfo(), False)
176-
# calling upgradewallet with explicit version number
177-
# should return nothing if successful
178-
assert_equal(wallet.upgradewallet(169900), {})
179-
new_version = wallet.getwalletinfo()["walletversion"]
180-
# upgraded wallet should have version 169900
181-
assert_equal(new_version, 169900)
183+
self.log.info("Test upgradewallet with explicit version number")
184+
self.test_upgradewallet(wallet, previous_version=60000, requested_version=169900)
182185
# after conversion master key hash should be present
183186
assert_is_hex_string(wallet.getwalletinfo()['hdseedid'])
184187

185-
self.log.info('Intermediary versions don\'t effect anything')
188+
self.log.info("Intermediary versions don't effect anything")
186189
copy_non_hd()
187190
# Wallet starts with 60000
188191
assert_equal(60000, wallet.getwalletinfo()['walletversion'])
189192
wallet.unloadwallet()
190193
before_checksum = sha256sum_file(node_master_wallet)
191194
node_master.loadwallet('')
192-
# Can "upgrade" to 129999 which should have no effect on the wallet
193-
wallet.upgradewallet(129999)
194-
assert_equal(60000, wallet.getwalletinfo()['walletversion'])
195+
# Test an "upgrade" from 60000 to 129999 has no effect, as the next version is 130000
196+
self.test_upgradewallet(wallet, previous_version=60000, requested_version=129999, expected_version=60000)
195197
wallet.unloadwallet()
196198
assert_equal(before_checksum, sha256sum_file(node_master_wallet))
197199
node_master.loadwallet('')
@@ -208,8 +210,7 @@ def copy_split_hd():
208210
orig_kvs = dump_bdb_kv(node_master_wallet)
209211
assert b'\x07hdchain' not in orig_kvs
210212
# Upgrade to HD, no split
211-
wallet.upgradewallet(130000)
212-
assert_equal(130000, wallet.getwalletinfo()['walletversion'])
213+
self.test_upgradewallet(wallet, previous_version=60000, requested_version=130000)
213214
# Check that there is now a hd chain and it is version 1, no internal chain counter
214215
new_kvs = dump_bdb_kv(node_master_wallet)
215216
assert b'\x07hdchain' in new_kvs
@@ -244,8 +245,7 @@ def copy_split_hd():
244245
assert_equal(130000, wallet.getwalletinfo()['walletversion'])
245246

246247
self.log.info('Upgrade HD to HD chain split')
247-
wallet.upgradewallet(169900)
248-
assert_equal(169900, wallet.getwalletinfo()['walletversion'])
248+
self.test_upgradewallet(wallet, previous_version=130000, requested_version=169900)
249249
# Check that the hdchain updated correctly
250250
new_kvs = dump_bdb_kv(node_master_wallet)
251251
hd_chain = new_kvs[b'\x07hdchain']
@@ -271,8 +271,7 @@ def copy_split_hd():
271271

272272
self.log.info('Upgrade non-HD to HD chain split')
273273
copy_non_hd()
274-
wallet.upgradewallet(169900)
275-
assert_equal(169900, wallet.getwalletinfo()['walletversion'])
274+
self.test_upgradewallet(wallet, previous_version=60000, requested_version=169900)
276275
# Check that the hdchain updated correctly
277276
new_kvs = dump_bdb_kv(node_master_wallet)
278277
hd_chain = new_kvs[b'\x07hdchain']
@@ -333,15 +332,15 @@ def copy_split_hd():
333332
# Check the wallet has a default key initially
334333
old_kvs = dump_bdb_kv(node_master_wallet)
335334
defaultkey = old_kvs[b'\x0adefaultkey']
336-
# Upgrade the wallet. Should still have the same default key
337-
wallet.upgradewallet(159900)
335+
self.log.info("Upgrade the wallet. Should still have the same default key.")
336+
self.test_upgradewallet(wallet, previous_version=139900, requested_version=159900)
338337
new_kvs = dump_bdb_kv(node_master_wallet)
339338
up_defaultkey = new_kvs[b'\x0adefaultkey']
340339
assert_equal(defaultkey, up_defaultkey)
341-
assert_equal(wallet.getwalletinfo()["walletversion"], 159900)
342340
# 0.16.3 doesn't have a default key
343341
v16_3_kvs = dump_bdb_kv(v16_3_wallet)
344342
assert b'\x0adefaultkey' not in v16_3_kvs
345343

344+
346345
if __name__ == '__main__':
347346
UpgradeWalletTest().main()

0 commit comments

Comments
 (0)