Skip to content

Commit cf57825

Browse files
committed
Merge #9614: [wallet] [refactor] Simplify getbalance implementation
02d9f50 [wallet] Remove unneeded legacy getbalance code (Russell Yanofsky) 82b7dc3 [wallet] Add GetLegacyBalance method to simplify getbalance RPC (Russell Yanofsky) Tree-SHA512: c3b890ff1f5a3df7e886309bad94bdf5cc3c12b72983bb79c72f8655ce16edf581bff0faaade2f18c2cb723f50d516e53f87792f81c3f8143b0c4377c0d80e87
2 parents 6fdb319 + 02d9f50 commit cf57825

File tree

3 files changed

+66
-108
lines changed

3 files changed

+66
-108
lines changed

src/wallet/rpcwallet.cpp

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,8 @@ UniValue getbalance(const JSONRPCRequest& request)
729729
if (request.params.size() == 0)
730730
return ValueFromAmount(pwallet->GetBalance());
731731

732+
const std::string* account = request.params[0].get_str() != "*" ? &request.params[0].get_str() : nullptr;
733+
732734
int nMinDepth = 1;
733735
if (request.params.size() > 1)
734736
nMinDepth = request.params[1].get_int();
@@ -737,41 +739,7 @@ UniValue getbalance(const JSONRPCRequest& request)
737739
if(request.params[2].get_bool())
738740
filter = filter | ISMINE_WATCH_ONLY;
739741

740-
if (request.params[0].get_str() == "*") {
741-
// Calculate total balance in a very different way from GetBalance().
742-
// The biggest difference is that GetBalance() sums up all unspent
743-
// TxOuts paying to the wallet, while this sums up both spent and
744-
// unspent TxOuts paying to the wallet, and then subtracts the values of
745-
// TxIns spending from the wallet. This also has fewer restrictions on
746-
// which unconfirmed transactions are considered trusted.
747-
CAmount nBalance = 0;
748-
for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
749-
const CWalletTx& wtx = pairWtx.second;
750-
if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
751-
continue;
752-
753-
CAmount allFee;
754-
std::string strSentAccount;
755-
std::list<COutputEntry> listReceived;
756-
std::list<COutputEntry> listSent;
757-
wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
758-
if (wtx.GetDepthInMainChain() >= nMinDepth)
759-
{
760-
BOOST_FOREACH(const COutputEntry& r, listReceived)
761-
nBalance += r.amount;
762-
}
763-
BOOST_FOREACH(const COutputEntry& s, listSent)
764-
nBalance -= s.amount;
765-
nBalance -= allFee;
766-
}
767-
return ValueFromAmount(nBalance);
768-
}
769-
770-
std::string strAccount = AccountFromValue(request.params[0]);
771-
772-
CAmount nBalance = pwallet->GetAccountBalance(strAccount, nMinDepth, filter);
773-
774-
return ValueFromAmount(nBalance);
742+
return ValueFromAmount(pwallet->GetLegacyBalance(filter, nMinDepth, account));
775743
}
776744

777745
UniValue getunconfirmedbalance(const JSONRPCRequest &request)
@@ -901,7 +869,7 @@ UniValue sendfrom(const JSONRPCRequest& request)
901869
EnsureWalletIsUnlocked(pwallet);
902870

903871
// Check funds
904-
CAmount nBalance = pwallet->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
872+
CAmount nBalance = pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, &strAccount);
905873
if (nAmount > nBalance)
906874
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
907875

@@ -1010,7 +978,7 @@ UniValue sendmany(const JSONRPCRequest& request)
1010978
EnsureWalletIsUnlocked(pwallet);
1011979

1012980
// Check funds
1013-
CAmount nBalance = pwallet->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
981+
CAmount nBalance = pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, &strAccount);
1014982
if (totalAmount > nBalance)
1015983
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
1016984

src/wallet/wallet.cpp

Lines changed: 58 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,41 +1457,6 @@ void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived,
14571457

14581458
}
14591459

1460-
void CWalletTx::GetAccountAmounts(const std::string& strAccount, CAmount& nReceived,
1461-
CAmount& nSent, CAmount& nFee, const isminefilter& filter) const
1462-
{
1463-
nReceived = nSent = nFee = 0;
1464-
1465-
CAmount allFee;
1466-
std::string strSentAccount;
1467-
std::list<COutputEntry> listReceived;
1468-
std::list<COutputEntry> listSent;
1469-
GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
1470-
1471-
if (strAccount == strSentAccount)
1472-
{
1473-
BOOST_FOREACH(const COutputEntry& s, listSent)
1474-
nSent += s.amount;
1475-
nFee = allFee;
1476-
}
1477-
{
1478-
LOCK(pwallet->cs_wallet);
1479-
BOOST_FOREACH(const COutputEntry& r, listReceived)
1480-
{
1481-
if (pwallet->mapAddressBook.count(r.destination))
1482-
{
1483-
std::map<CTxDestination, CAddressBookData>::const_iterator mi = pwallet->mapAddressBook.find(r.destination);
1484-
if (mi != pwallet->mapAddressBook.end() && (*mi).second.name == strAccount)
1485-
nReceived += r.amount;
1486-
}
1487-
else if (strAccount.empty())
1488-
{
1489-
nReceived += r.amount;
1490-
}
1491-
}
1492-
}
1493-
}
1494-
14951460
/**
14961461
* Scan the block chain (starting in pindexStart) for transactions
14971462
* from or to us. If fUpdate is true, found transactions that already
@@ -1975,6 +1940,49 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const
19751940
return nTotal;
19761941
}
19771942

1943+
// Calculate total balance in a different way from GetBalance. The biggest
1944+
// difference is that GetBalance sums up all unspent TxOuts paying to the
1945+
// wallet, while this sums up both spent and unspent TxOuts paying to the
1946+
// wallet, and then subtracts the values of TxIns spending from the wallet. This
1947+
// also has fewer restrictions on which unconfirmed transactions are considered
1948+
// trusted.
1949+
CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth, const std::string* account) const
1950+
{
1951+
LOCK2(cs_main, cs_wallet);
1952+
1953+
CAmount balance = 0;
1954+
for (const auto& entry : mapWallet) {
1955+
const CWalletTx& wtx = entry.second;
1956+
const int depth = wtx.GetDepthInMainChain();
1957+
if (depth < 0 || !CheckFinalTx(*wtx.tx) || wtx.GetBlocksToMaturity() > 0) {
1958+
continue;
1959+
}
1960+
1961+
// Loop through tx outputs and add incoming payments. For outgoing txs,
1962+
// treat change outputs specially, as part of the amount debited.
1963+
CAmount debit = wtx.GetDebit(filter);
1964+
const bool outgoing = debit > 0;
1965+
for (const CTxOut& out : wtx.tx->vout) {
1966+
if (outgoing && IsChange(out)) {
1967+
debit -= out.nValue;
1968+
} else if (IsMine(out) & filter && depth >= minDepth && (!account || *account == GetAccountName(out.scriptPubKey))) {
1969+
balance += out.nValue;
1970+
}
1971+
}
1972+
1973+
// For outgoing txs, subtract amount debited.
1974+
if (outgoing && (!account || *account == wtx.strFromAccount)) {
1975+
balance -= debit;
1976+
}
1977+
}
1978+
1979+
if (account) {
1980+
balance += CWalletDB(*dbw).GetAccountCreditDebit(*account);
1981+
}
1982+
1983+
return balance;
1984+
}
1985+
19781986
void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe, const CCoinControl *coinControl, bool fIncludeZeroValue) const
19791987
{
19801988
vCoins.clear();
@@ -2911,6 +2919,21 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
29112919
return CWalletDB(*dbw).EraseName(CBitcoinAddress(address).ToString());
29122920
}
29132921

2922+
const std::string& CWallet::GetAccountName(const CScript& scriptPubKey) const
2923+
{
2924+
CTxDestination address;
2925+
if (ExtractDestination(scriptPubKey, address) && !scriptPubKey.IsUnspendable()) {
2926+
auto mi = mapAddressBook.find(address);
2927+
if (mi != mapAddressBook.end()) {
2928+
return mi->second.name;
2929+
}
2930+
}
2931+
// A scriptPubKey that doesn't have an entry in the address book is
2932+
// associated with the default account ("").
2933+
const static std::string DEFAULT_ACCOUNT_NAME;
2934+
return DEFAULT_ACCOUNT_NAME;
2935+
}
2936+
29142937
bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
29152938
{
29162939
if (!CWalletDB(*dbw).WriteDefaultKey(vchPubKey))
@@ -3257,37 +3280,6 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
32573280
return ret;
32583281
}
32593282

3260-
CAmount CWallet::GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter)
3261-
{
3262-
CWalletDB walletdb(*dbw);
3263-
return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
3264-
}
3265-
3266-
CAmount CWallet::GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, int nMinDepth, const isminefilter& filter)
3267-
{
3268-
CAmount nBalance = 0;
3269-
3270-
// Tally wallet transactions
3271-
for (std::map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
3272-
{
3273-
const CWalletTx& wtx = (*it).second;
3274-
if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
3275-
continue;
3276-
3277-
CAmount nReceived, nSent, nFee;
3278-
wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
3279-
3280-
if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
3281-
nBalance += nReceived;
3282-
nBalance -= nSent + nFee;
3283-
}
3284-
3285-
// Tally internal accounting entries
3286-
nBalance += walletdb.GetAccountCreditDebit(strAccount);
3287-
3288-
return nBalance;
3289-
}
3290-
32913283
std::set<CTxDestination> CWallet::GetAccountAddresses(const std::string& strAccount) const
32923284
{
32933285
LOCK(cs_wallet);

src/wallet/wallet.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -451,9 +451,6 @@ class CWalletTx : public CMerkleTx
451451
void GetAmounts(std::list<COutputEntry>& listReceived,
452452
std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const;
453453

454-
void GetAccountAmounts(const std::string& strAccount, CAmount& nReceived,
455-
CAmount& nSent, CAmount& nFee, const isminefilter& filter) const;
456-
457454
bool IsFromMe(const isminefilter& filter) const
458455
{
459456
return (GetDebit(filter) > 0);
@@ -918,6 +915,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
918915
CAmount GetWatchOnlyBalance() const;
919916
CAmount GetUnconfirmedWatchOnlyBalance() const;
920917
CAmount GetImmatureWatchOnlyBalance() const;
918+
CAmount GetLegacyBalance(const isminefilter& filter, int minDepth, const std::string* account) const;
921919

922920
/**
923921
* Insert additional inputs into the transaction by
@@ -972,8 +970,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
972970
std::set< std::set<CTxDestination> > GetAddressGroupings();
973971
std::map<CTxDestination, CAmount> GetAddressBalances();
974972

975-
CAmount GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter);
976-
CAmount GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, int nMinDepth, const isminefilter& filter);
977973
std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const;
978974

979975
isminetype IsMine(const CTxIn& txin) const;
@@ -1004,6 +1000,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
10041000

10051001
bool DelAddressBook(const CTxDestination& address);
10061002

1003+
const std::string& GetAccountName(const CScript& scriptPubKey) const;
1004+
10071005
void Inventory(const uint256 &hash) override
10081006
{
10091007
{

0 commit comments

Comments
 (0)