Merge getrpcwhitelist_wallets-25+knots

This commit is contained in:
Luke Dashjr 2023-11-15 23:49:11 +00:00
commit 6b83f6e186
2 changed files with 70 additions and 0 deletions

View File

@ -6,6 +6,7 @@
#include <rpc/server.h>
#include <httprpc.h>
#include <node/context.h>
#include <rpc/util.h>
#include <shutdown.h>
#include <sync.h>
@ -14,6 +15,11 @@
#include <util/system.h>
#include <util/time.h>
#ifdef ENABLE_WALLET
#include <interfaces/wallet.h>
#include <wallet/wallet.h>
#endif
#include <boost/signals2/signal.hpp>
#include <cassert>
@ -263,6 +269,10 @@ static RPCHelpMan getrpcwhitelist()
{
{RPCResult::Type::NONE, "rpc", "Key is name of RPC method, value is null"},
}},
{RPCResult::Type::OBJ_DYN, "wallets", "List of wallets that the user is allowed to access",
{
{RPCResult::Type::NONE, "wallet_name", "Key is name of wallet, value is null"},
}},
}
},
RPCExamples{
@ -276,8 +286,31 @@ static RPCHelpMan getrpcwhitelist()
whitelisted_rpcs.pushKV(rpc, NullUniValue);
}
UniValue whitelisted_wallets(UniValue::VOBJ);
#ifdef ENABLE_WALLET
std::string authorized_wallet_name;
const bool have_wallet_restriction = GetWalletRestrictionFromJSONRPCRequest(request, authorized_wallet_name);
if (have_wallet_restriction) {
if (authorized_wallet_name != "-") {
whitelisted_wallets.pushKV(authorized_wallet_name, NullUniValue);
}
} else {
// All wallets are allowed
auto node_context = util::AnyPtr<node::NodeContext>(request.context);
if (node_context && node_context->wallet_loader && node_context->wallet_loader->context()) {
for (const std::shared_ptr<wallet::CWallet>& wallet : wallet::GetWallets(*node_context->wallet_loader->context())) {
if (!wallet.get()) continue;
LOCK(wallet->cs_wallet);
whitelisted_wallets.pushKV(wallet->GetName(), NullUniValue);
}
}
}
#endif
UniValue result(UniValue::VOBJ);
result.pushKV("methods", whitelisted_rpcs);
result.pushKV("wallets", whitelisted_wallets);
return result;
}

View File

@ -32,8 +32,13 @@ def call_rpc(node, settings, rpc):
return {"status": code, "json": json_ret['result']}
class RPCWhitelistTest(BitcoinTestFramework):
def add_options(self, parser):
self.add_wallet_options(parser)
def set_test_params(self):
self.num_nodes = 1
if self.is_wallet_compiled():
self.skip_if_no_wallet()
def setup_chain(self):
super().setup_chain()
@ -45,6 +50,14 @@ class RPCWhitelistTest(BitcoinTestFramework):
"f3d319f64b076012f75626c9d895fced$7f55381a24fda02c5de7c18fc377f56fc573149b4d6f83daa9fd584210b51f99",
"dummy2pwd",
"getbalance,getwalletinfo"]
self.settings3 = ["dummy3",
"7afab69a70b08a1499a5a9031eaa5479$a3bcfa66a0050564afe4f86300f95be2432cf9581dc6f51eb831f8671650587a",
"dummy3pwd",
"getrpcwhitelist"]
self.settings4 = ["dummy4",
"487024a6853066e1faecfd8a7bb46c63$3ac8b40945d1eeb735da6429db1fe6a179994ed8a0bc01590da1552935f41623",
"dummy4pwd",
"getrpcwhitelist"]
# declare rpc-whitelisting entries
with open(os.path.join(get_datadir_path(self.options.tmpdir, 0), "bitcoin.conf"), 'a', encoding='utf8') as f:
@ -53,8 +66,15 @@ class RPCWhitelistTest(BitcoinTestFramework):
f.write("rpcwhitelist={}:{}\n".format(self.settings[0], self.settings[3]))
f.write("rpcauth={}:{}\n".format(self.settings_forbidden[0], self.settings_forbidden[1]))
f.write("rpcwhitelist={}:{}\n".format(self.settings_forbidden[0], self.settings_forbidden[3]))
f.write("rpcauth={}:{}:-\n".format(self.settings3[0], self.settings3[1]))
f.write("rpcwhitelist={}:{}\n".format(self.settings3[0], self.settings3[3]))
f.write("rpcauth={}:{}:second\n".format(self.settings4[0], self.settings4[1]))
f.write("rpcwhitelist={}:{}\n".format(self.settings4[0], self.settings4[3]))
def run_test(self):
if self.is_wallet_compiled():
self.nodes[0].createwallet('second')
self.log.info("Test getrpcwhitelist")
whitelisted = {method: None for method in self.settings[3].split(',')}
@ -62,6 +82,23 @@ class RPCWhitelistTest(BitcoinTestFramework):
result = call_rpc(self.nodes[0], self.settings, 'getrpcwhitelist')
assert_equal(200, result['status'])
assert_equal(result['json']['methods'], whitelisted)
if self.is_wallet_compiled():
assert_equal(result['json']['wallets'], {self.default_wallet_name: None, 'second': None})
else:
assert_equal(result['json']['wallets'], {})
whitelisted = {method: None for method in self.settings3[3].split(',')}
result = call_rpc(self.nodes[0], self.settings3, 'getrpcwhitelist')
assert_equal(200, result['status'])
assert_equal(result['json']['methods'], whitelisted)
assert_equal(result['json']['wallets'], {})
if self.is_wallet_compiled():
result = call_rpc(self.nodes[0], self.settings4, 'getrpcwhitelist')
assert_equal(200, result['status'])
assert_equal(result['json']['methods'], whitelisted)
assert_equal(result['json']['wallets'], {'second':None})
# should fail because user has no rpcwhitelist-rpc entry in bitcoin.conf
result = call_rpc(self.nodes[0], self.settings_forbidden, 'getrpcwhitelist')
assert_equal(result['status'], 403)