Merge 19089 via cli_getinfo_mwbalances-28+knots

This commit is contained in:
Luke Dashjr 2025-03-05 03:27:08 +00:00
commit e937882a24
3 changed files with 45 additions and 6 deletions

View File

@ -90,7 +90,7 @@ static void SetupCliArgs(ArgsManager& argsman)
DEFAULT_NBLOCKS, DEFAULT_MAX_TRIES),
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-addrinfo", "Get the number of addresses known to the node, per network and total, after filtering for quality and recency. The total number of addresses known to the node may be higher.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-getinfo", "Get general information from the remote server. Note that unlike server-side RPC calls, the output of -getinfo is the result of multiple non-atomic requests. Some entries in the output may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-getinfo", "Get general information from the remote server, including the balances of each loaded wallet when in multiwallet mode. Note that -getinfo is the combined result of several RPCs (getnetworkinfo, getblockchaininfo, getwalletinfo, getbalances, and in multiwallet mode, listwallets), each with potentially different state.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-netinfo", strprintf("Get network peer connection information from the remote server. An optional argument from 0 to %d can be passed for different peers listings (default: 0). If a non-zero value is passed, an additional \"outonly\" (or \"o\") argument can be passed to see outbound peers only. Pass \"help\" (or \"h\") for detailed help documentation.", NETINFO_MAX_LEVEL), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
SetupChainParamsBaseOptions(argsman);
@ -1283,7 +1283,7 @@ static int CommandLineRPC(int argc, char *argv[])
}
std::unique_ptr<BaseRequestHandler> rh;
std::string method;
if (gArgs.IsArgSet("-getinfo")) {
if (gArgs.GetBoolArg("-getinfo", false)) {
rh.reset(new GetinfoRequestHandler());
} else if (gArgs.GetBoolArg("-netinfo", false)) {
if (!args.empty() && (args.at(0) == "h" || args.at(0) == "help")) {

View File

@ -15,6 +15,7 @@ from test_framework.util import (
assert_greater_than_or_equal,
assert_raises_process_error,
assert_raises_rpc_error,
assert_scale,
get_auth_cookie,
rpc_port,
)
@ -88,9 +89,8 @@ class TestBitcoinCli(BitcoinTestFramework):
self.generate(self.nodes[0], BLOCKS)
self.log.info("Compare responses from getblockchaininfo RPC and `bitcoin-cli getblockchaininfo`")
cli_response = self.nodes[0].cli.getblockchaininfo()
rpc_response = self.nodes[0].getblockchaininfo()
assert_equal(cli_response, rpc_response)
blockchain_info = self.nodes[0].getblockchaininfo()
assert_equal(blockchain_info, self.nodes[0].cli.getblockchaininfo())
self.log.info("Test named arguments")
assert_equal(self.nodes[0].cli.echo(0, 1, arg3=3, arg5=5), ['0', '1', None, '3', None, '5'])
@ -179,6 +179,22 @@ class TestBitcoinCli(BitcoinTestFramework):
self.log.info("Test -getinfo with invalid value for -color option")
assert_raises_process_error(1, "Invalid value for -color option. Valid values: always, auto, never.", self.nodes[0].cli('-getinfo', '-color=foo').send_cli)
self.log.info("Test -getinfo command parsing")
self.log.debug("Test -getinfo=1 and -getinfo=-1 both succeed")
for cmd in ['-getinfo=1', '-getinfo=-1']:
assert_equal(str(blockchain_info['blocks']), cli_get_info_string_to_dict(self.nodes[0].cli(cmd).send_cli())['Blocks'])
self.log.debug("Test -getinfo=0 and -nogetinfo both raise 'too few parameters'")
err_msg = "error: too few parameters (need at least command)"
for cmd in ['-getinfo=0', '-nogetinfo']:
assert_raises_process_error(1, err_msg, self.nodes[0].cli(cmd).send_cli)
self.log.debug("Test -igetinfo and -getinfos both raise 'Invalid parameter'")
err_msg = "Error parsing command line arguments: Invalid parameter"
for cmd in ['-igetinfo', '-getinfos']:
assert_raises_process_error(1, "{} {}".format(err_msg, cmd), self.nodes[0].cli(cmd).send_cli)
self.log.info("Test -getinfo returns expected network and blockchain info")
if self.is_specified_wallet_compiled():
self.import_deterministic_coinbase_privkeys()
@ -187,7 +203,7 @@ class TestBitcoinCli(BitcoinTestFramework):
cli_get_info = cli_get_info_string_to_dict(cli_get_info_string)
network_info = self.nodes[0].getnetworkinfo()
blockchain_info = self.nodes[0].getblockchaininfo()
assert_equal(cli_get_info['Chain'], self.chain)
assert_equal(int(cli_get_info['Version']), network_info['version'])
assert_equal(cli_get_info['Verification progress'], "%.4f%%" % (blockchain_info['verificationprogress'] * 100))
assert_equal(int(cli_get_info['Blocks']), blockchain_info['blocks'])
@ -198,6 +214,10 @@ class TestBitcoinCli(BitcoinTestFramework):
assert_equal(cli_get_info['Proxies'], network_info['networks'][0]['proxy'])
assert_equal(Decimal(cli_get_info['Difficulty']), blockchain_info['difficulty'])
assert_equal(cli_get_info['Chain'], blockchain_info['chain'])
for field in ['Blocks', 'Headers', 'Time offset (s)', 'Version']:
assert_scale(int(cli_get_info[field]), expected_scale=0)
for field in ('connections_in', 'connections_out', 'connections'):
assert_scale(network_info[field], expected_scale=0)
self.log.info("Test -getinfo and bitcoin-cli return all proxies")
self.restart_node(0, extra_args=["-proxy=127.0.0.1:9050", "-i2psam=127.0.0.1:7656"])
@ -219,6 +239,10 @@ class TestBitcoinCli(BitcoinTestFramework):
assert_equal(Decimal(cli_get_info['Transaction fee rate (-paytxfee) (BTC/kvB)']), wallet_info['paytxfee'])
assert_equal(Decimal(cli_get_info['Min tx relay fee rate (BTC/kvB)']), network_info['relayfee'])
assert_equal(self.nodes[0].cli.getwalletinfo(), wallet_info)
for field in ['Keypool size', 'Time offset (s)', 'Unlocked until']:
assert_scale(cli_get_info[field], expected_scale=0)
for field in ['Balance', 'Transaction fee rate (-paytxfee) (BTC/kvB)', 'Min tx relay fee rate (BTC/kvB)']:
assert_scale(cli_get_info[field])
# Setup to test -getinfo, -generate, and -rpcwallet= with multiple wallets.
wallets = [self.default_wallet_name, 'Encrypted', 'secret']
@ -245,6 +269,7 @@ class TestBitcoinCli(BitcoinTestFramework):
assert 'Balances' not in cli_get_info_string
assert_equal(cli_get_info["Wallet"], wallets[i])
assert_equal(Decimal(cli_get_info['Balance']), amounts[i])
assert_scale(Decimal(cli_get_info['Balance']))
self.log.info("Test -getinfo with multiple wallets and -rpcwallet=non-existing-wallet returns no balances")
cli_get_info_string = self.nodes[0].cli('-getinfo', '-rpcwallet=does-not-exist').send_cli()
@ -258,6 +283,7 @@ class TestBitcoinCli(BitcoinTestFramework):
assert 'Balance' not in cli_get_info
for k, v in zip(wallets, amounts):
assert_equal(Decimal(cli_get_info['Balances'][k]), v)
assert_scale(Decimal(cli_get_info['Balances'][k]))
# Unload the default wallet and re-verify.
self.nodes[0].unloadwallet(wallets[0])
@ -278,6 +304,7 @@ class TestBitcoinCli(BitcoinTestFramework):
assert 'Balances' not in cli_get_info_string
assert_equal(cli_get_info['Wallet'], wallets[1])
assert_equal(Decimal(cli_get_info['Balance']), amounts[1])
assert_scale(Decimal(cli_get_info['Balance']))
self.log.info("Test -getinfo with -rpcwallet=remaining-non-default-wallet returns only its balance")
cli_get_info_string = self.nodes[0].cli('-getinfo', rpcwallet2).send_cli()

View File

@ -216,6 +216,18 @@ def assert_array_result(object_array, to_match, expected, should_not_find=False)
if num_matched > 0 and should_not_find:
raise AssertionError("Objects were found %s" % (str(to_match)))
def assert_scale(number, expected_scale=8):
"""Assert number has expected scale, e.g. fractional digits; number of
digits after the decimal. The default of 8 corresponds to a Bitcoin amount."""
number = str(number)
mantissa = number.split('.')[-1].upper()
if mantissa[:3] == '0E-':
assert_equal(mantissa, '0E-{}'.format(expected_scale)) # zeros in exponent notation
elif mantissa == number:
assert_equal(0, expected_scale) # no mantissa, ergo, expected scale must be 0
else:
assert_equal(len(mantissa), expected_scale)
# Utility functions
###################