mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-24 10:17:45 -03:00
Merge 5d0c836294
into 66aa6a47bd
This commit is contained in:
commit
360def914b
8 changed files with 31 additions and 12 deletions
9
doc/release-notes-31353.md
Normal file
9
doc/release-notes-31353.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
Updated RPCs
|
||||
------------
|
||||
|
||||
- RPC getbalances has a new `total` field that provides the sum of all wallet
|
||||
balances returned by the RPC. (#31353)
|
||||
|
||||
- CLI -getinfo now displays wallet balances from RPC getbalances `total` instead
|
||||
of `mine.trusted` in order to include watchonly, reused, untrusted pending, and
|
||||
immature coinbase outputs in the balance shown. (#31353)
|
|
@ -374,7 +374,7 @@ public:
|
|||
result.pushKV("paytxfee", batch[ID_WALLETINFO]["result"]["paytxfee"]);
|
||||
}
|
||||
if (!batch[ID_BALANCES]["result"].isNull()) {
|
||||
result.pushKV("balance", batch[ID_BALANCES]["result"]["mine"]["trusted"]);
|
||||
result.pushKV("balance", batch[ID_BALANCES]["result"]["total"]);
|
||||
}
|
||||
result.pushKV("relayfee", batch[ID_NETWORKINFO]["result"]["relayfee"]);
|
||||
result.pushKV("warnings", batch[ID_NETWORKINFO]["result"]["warnings"]);
|
||||
|
@ -1007,7 +1007,7 @@ static void ParseError(const UniValue& error, std::string& strPrint, int& nRet)
|
|||
|
||||
/**
|
||||
* GetWalletBalances calls listwallets; if more than one wallet is loaded, it then
|
||||
* fetches mine.trusted balances for each loaded wallet and pushes them to `result`.
|
||||
* fetches the total balance for each loaded wallet and pushes it to `result`.
|
||||
*
|
||||
* @param result Reference to UniValue object the wallet names and balances are pushed to.
|
||||
*/
|
||||
|
@ -1023,7 +1023,7 @@ static void GetWalletBalances(UniValue& result)
|
|||
for (const UniValue& wallet : wallets.getValues()) {
|
||||
const std::string& wallet_name = wallet.get_str();
|
||||
const UniValue getbalances = ConnectAndCallRPC(&rh, "getbalances", /* args=*/{}, wallet_name);
|
||||
const UniValue& balance = getbalances.find_value("result")["mine"]["trusted"];
|
||||
const UniValue& balance = getbalances.find_value("result")["total"];
|
||||
balances.pushKV(wallet_name, balance);
|
||||
}
|
||||
result.pushKV("balances", std::move(balances));
|
||||
|
|
|
@ -314,6 +314,7 @@ Balance GetBalance(const CWallet& wallet, const int min_depth, bool avoid_reuse)
|
|||
}
|
||||
ret.m_mine_immature += CachedTxGetImmatureCredit(wallet, wtx, ISMINE_SPENDABLE);
|
||||
ret.m_watchonly_immature += CachedTxGetImmatureCredit(wallet, wtx, ISMINE_WATCH_ONLY);
|
||||
ret.m_total = ret.m_mine_trusted + ret.m_mine_untrusted_pending + ret.m_mine_immature + ret.m_watchonly_trusted + ret.m_watchonly_untrusted_pending + ret.m_watchonly_immature;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
|
|
@ -55,6 +55,7 @@ struct Balance {
|
|||
CAmount m_watchonly_trusted{0};
|
||||
CAmount m_watchonly_untrusted_pending{0};
|
||||
CAmount m_watchonly_immature{0};
|
||||
CAmount m_total{0};
|
||||
};
|
||||
Balance GetBalance(const CWallet& wallet, int min_depth = 0, bool avoid_reuse = true);
|
||||
|
||||
|
|
|
@ -447,6 +447,7 @@ RPCHelpMan getbalances()
|
|||
{RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"},
|
||||
}},
|
||||
RESULT_LAST_PROCESSED_BLOCK,
|
||||
{RPCResult::Type::STR_AMOUNT, "total", "total of all balances returned by this RPC"},
|
||||
}
|
||||
},
|
||||
RPCExamples{
|
||||
|
@ -466,6 +467,7 @@ RPCHelpMan getbalances()
|
|||
|
||||
const auto bal = GetBalance(wallet);
|
||||
UniValue balances{UniValue::VOBJ};
|
||||
const Balance full_bal{GetBalance(wallet, /*min_depth=*/0, /*avoid_reuse=*/false)};
|
||||
{
|
||||
UniValue balances_mine{UniValue::VOBJ};
|
||||
balances_mine.pushKV("trusted", ValueFromAmount(bal.m_mine_trusted));
|
||||
|
@ -474,7 +476,6 @@ RPCHelpMan getbalances()
|
|||
if (wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
|
||||
// If the AVOID_REUSE flag is set, bal has been set to just the un-reused address balance. Get
|
||||
// the total balance, and then subtract bal to get the reused address balance.
|
||||
const auto full_bal = GetBalance(wallet, 0, false);
|
||||
balances_mine.pushKV("used", ValueFromAmount(full_bal.m_mine_trusted + full_bal.m_mine_untrusted_pending - bal.m_mine_trusted - bal.m_mine_untrusted_pending));
|
||||
}
|
||||
balances.pushKV("mine", std::move(balances_mine));
|
||||
|
@ -489,6 +490,7 @@ RPCHelpMan getbalances()
|
|||
}
|
||||
|
||||
AppendLastProcessedBlock(balances, wallet);
|
||||
balances.pushKV("total", ValueFromAmount(full_bal.m_total));
|
||||
return balances;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -21,10 +21,9 @@ from test_framework.util import (
|
|||
import time
|
||||
|
||||
# The block reward of coinbaseoutput.nValue (50) BTC/block matures after
|
||||
# COINBASE_MATURITY (100) blocks. Therefore, after mining 101 blocks we expect
|
||||
# node 0 to have a balance of (BLOCKS - COINBASE_MATURITY) * 50 BTC/block.
|
||||
# COINBASE_MATURITY (100) blocks.
|
||||
BLOCKS = COINBASE_MATURITY + 1
|
||||
BALANCE = (BLOCKS - 100) * 50
|
||||
BALANCE = BLOCKS * 50
|
||||
|
||||
JSON_PARSING_ERROR = 'error: Error parsing JSON: foo'
|
||||
BLOCKS_VALUE_OF_ZERO = 'error: the first argument (number of blocks to generate, default: 1) must be an integer value greater than zero'
|
||||
|
@ -222,7 +221,7 @@ class TestBitcoinCli(BitcoinTestFramework):
|
|||
|
||||
# Setup to test -getinfo, -generate, and -rpcwallet= with multiple wallets.
|
||||
wallets = [self.default_wallet_name, 'Encrypted', 'secret']
|
||||
amounts = [BALANCE + Decimal('9.999928'), Decimal(9), Decimal(31)]
|
||||
amounts = [BALANCE, 9, 31]
|
||||
self.nodes[0].createwallet(wallet_name=wallets[1])
|
||||
self.nodes[0].createwallet(wallet_name=wallets[2])
|
||||
w1 = self.nodes[0].get_wallet_rpc(wallets[0])
|
||||
|
@ -234,9 +233,11 @@ class TestBitcoinCli(BitcoinTestFramework):
|
|||
w2.encryptwallet(password)
|
||||
w1.sendtoaddress(w2.getnewaddress(), amounts[1])
|
||||
w1.sendtoaddress(w3.getnewaddress(), amounts[2])
|
||||
amounts[0] -= (amounts[1] + amounts[2])
|
||||
|
||||
# Mine a block to confirm; adds a block reward (50 BTC) to the default wallet.
|
||||
self.generate(self.nodes[0], 1)
|
||||
amounts[0] += 50
|
||||
|
||||
self.log.info("Test -getinfo with multiple wallets and -rpcwallet returns specified wallet balance")
|
||||
for i in range(len(wallets)):
|
||||
|
|
|
@ -59,9 +59,12 @@ def assert_unspent(node, total_count=None, total_sum=None, reused_supported=None
|
|||
|
||||
def assert_balances(node, mine, margin=0.001):
|
||||
'''Make assertions about a node's getbalances output'''
|
||||
got = node.getbalances()["mine"]
|
||||
balances, total = node.getbalances(), 0
|
||||
for k,v in mine.items():
|
||||
assert_approx(got[k], v, margin)
|
||||
assert_approx(balances["mine"][k], v, margin)
|
||||
total += v
|
||||
assert_approx(balances["total"], total, margin)
|
||||
|
||||
|
||||
class AvoidReuseTest(BitcoinTestFramework):
|
||||
def add_options(self, parser):
|
||||
|
|
|
@ -176,10 +176,12 @@ class WalletTest(BitcoinTestFramework):
|
|||
'untrusted_pending': Decimal('60.0')},
|
||||
'watchonly': {'immature': Decimal('5000'),
|
||||
'trusted': Decimal('50.0'),
|
||||
'untrusted_pending': Decimal('0E-8')}}
|
||||
'untrusted_pending': Decimal('0E-8')},
|
||||
'total': Decimal('69.99' if self.options.descriptors else '5119.99')}
|
||||
expected_balances_1 = {'mine': {'immature': Decimal('0E-8'),
|
||||
'trusted': Decimal('0E-8'), # node 1's send had an unsafe input
|
||||
'untrusted_pending': Decimal('30.0') - fee_node_1}} # Doesn't include output of node 0's send since it was spent
|
||||
'untrusted_pending': Decimal('30.0') - fee_node_1}, # Doesn't include output of node 0's send since it was spent
|
||||
'total': Decimal('30.0') - fee_node_1}
|
||||
if self.options.descriptors:
|
||||
del expected_balances_0["watchonly"]
|
||||
balances_0 = self.nodes[0].getbalances()
|
||||
|
|
Loading…
Add table
Reference in a new issue