From 24f5767922c8b375d175f5eec46bfa0ec42ff18f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 21 Jul 2017 15:34:11 +0200 Subject: [PATCH] Merge #10604: [wallet] [tests] Add listwallets RPC, include wallet name in `getwalletinfo` and add multiwallet test 3707fcd [wallet] [tests] Add listwallets to multiwallet test (John Newbery) 9508761 [wallet] [rpc] Add listwallets RPC (John Newbery) 4a05715 [wallet] [rpc] print wallet name in getwalletinfo (John Newbery) 09eacee [wallet] fix comment for CWallet::Verify() (John Newbery) Pull request description: - fix comment for CWallet::Verify (cleanup after #8694) - expose the wallet name in `getwalletinfo` rpc - add `listwallets` rpc - returns array of wallet names - add functional test for multiwallet using new rpc functionality Tree-SHA512: 52f864726bf8a28421d4f3604a6cb95fffb3f4e19edbce18efaef06142c48dd4adb9e7a65a10de2955c80f13c00803ce27c78ccbc8434d92ef12cd36c4ccb4aa --- src/wallet/rpcwallet.cpp | 37 ++++++++++++++++++++++++++++++++++ src/wallet/wallet.h | 4 +++- test/functional/multiwallet.py | 31 +++++++++++++++++++--------- test/functional/test_runner.py | 1 + 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 23732268994235..3ea7c808375c5a 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2452,6 +2452,7 @@ UniValue getwalletinfo(const JSONRPCRequest& request) "Returns an object containing various wallet state info.\n" "\nResult:\n" "{\n" + " \"walletname\": xxxxx, (string) the wallet name\n" " \"walletversion\": xxxxx, (numeric) the wallet version\n" " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n" " \"privatesend_balance\": xxxxxx, (numeric) the anonymized dash balance of the wallet in " + CURRENCY_UNIT + "\n" @@ -2485,6 +2486,8 @@ UniValue getwalletinfo(const JSONRPCRequest& request) CHDChain hdChainCurrent; bool fHDEnabled = pwallet->GetHDChain(hdChainCurrent); UniValue obj(UniValue::VOBJ); + + obj.push_back(Pair("walletname", pwallet->GetName())); obj.push_back(Pair("walletversion", pwallet->GetVersion())); obj.push_back(Pair("balance", ValueFromAmount(pwallet->GetBalance()))); obj.push_back(Pair("privatesend_balance", ValueFromAmount(pwallet->GetAnonymizedBalance()))); @@ -2522,6 +2525,39 @@ UniValue getwalletinfo(const JSONRPCRequest& request) return obj; } +UniValue listwallets(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() != 0) + throw std::runtime_error( + "listwallets\n" + "Returns a list of currently loaded wallets.\n" + "For full information on the wallet, use \"getwalletinfo\"\n" + "\nResult:\n" + "[ (json array of strings)\n" + " \"walletname\" (string) the wallet name\n" + " ...\n" + "]\n" + "\nExamples:\n" + + HelpExampleCli("listwallets", "") + + HelpExampleRpc("listwallets", "") + ); + + UniValue obj(UniValue::VARR); + + for (CWalletRef pwallet : vpwallets) { + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + LOCK(pwallet->cs_wallet); + + obj.push_back(pwallet->GetName()); + } + + return obj; +} + UniValue keepass(const JSONRPCRequest& request) { CWallet* const pwallet = GetWalletForJSONRPCRequest(request); @@ -3050,6 +3086,7 @@ static const CRPCCommand commands[] = { "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly"} }, { "wallet", "listtransactions", &listtransactions, false, {"account","count","skip","include_watchonly"} }, { "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe","query_options"} }, + { "wallet", "listwallets", &listwallets, true, {} }, { "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} }, { "wallet", "move", &movecmd, false, {"fromaccount","toaccount","amount","minconf","comment"} }, { "wallet", "sendfrom", &sendfrom, false, {"fromaccount","toaddress","amount","minconf","addlocked","comment","comment_to"} }, diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 7cfc863548caa1..e1d1d5fc5ff40b 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1163,7 +1163,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface //! Flush wallet (bitdb flush) void Flush(bool shutdown=false); - //! Verify the wallet database and perform salvage if required + //! Responsible for reading and validating the -wallet arguments and verifying the wallet database. + // This function will perform salvage on the wallet if requested, as long as only one wallet is + // being loaded (CWallet::ParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet). static bool Verify(); /** diff --git a/test/functional/multiwallet.py b/test/functional/multiwallet.py index 9a6e6ebdcab63e..bb577843761868 100755 --- a/test/functional/multiwallet.py +++ b/test/functional/multiwallet.py @@ -2,9 +2,12 @@ # Copyright (c) 2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -"""Test multiwallet.""" +"""Test multiwallet. + +Verify that a bitcoind node can load multiple wallet files +""" from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * +from test_framework.util import assert_equal, assert_raises_jsonrpc class MultiWalletTest(BitcoinTestFramework): @@ -18,20 +21,28 @@ def run_test(self): w1 = self.nodes[0] / "wallet/w1" w1.generate(1) - #accessing wallet RPC without using wallet endpoint fails + # accessing wallet RPC without using wallet endpoint fails assert_raises_jsonrpc(-32601, "Method not found", self.nodes[0].getwalletinfo) - #check w1 wallet balance - walletinfo = w1.getwalletinfo() - assert_equal(walletinfo['immature_balance'], 500) + # check w1 wallet balance + w1_info = w1.getwalletinfo() + assert_equal(w1_info['immature_balance'], 500) + w1_name = w1_info['walletname'] + assert_equal(w1_name, "w1") - #check w1 wallet balance + # check w1 wallet balance w2 = self.nodes[0] / "wallet/w2" - walletinfo = w2.getwalletinfo() - assert_equal(walletinfo['immature_balance'], 0) + w2_info = w2.getwalletinfo() + assert_equal(w2_info['immature_balance'], 0) + w2_name = w2_info['walletname'] + assert_equal(w2_name, "w2") w3 = self.nodes[0] / "wallet/w3" - + w3_name = w3.getwalletinfo()['walletname'] + assert_equal(w3_name, "w3") + + assert_equal({"w1", "w2", "w3"}, {w1_name, w2_name, w3_name}) + w1.generate(101) assert_equal(w1.getbalance(), 1000) assert_equal(w2.getbalance(), 0) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index ebddb704ce6f51..0357262c455edc 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -96,6 +96,7 @@ 'mempool_spendcoinbase.py', 'mempool_reorg.py', 'mempool_persist.py', + 'multiwallet.py', 'httpbasics.py', 'multi_rpc.py', 'proxy_test.py',