From d4640d7d8c3ba373195d33ab75db9c8cb43f8806 Mon Sep 17 00:00:00 2001 From: JaSK Date: Tue, 8 Apr 2014 15:23:50 +0200 Subject: [PATCH] Added argument to getbalance to include watchonly addresses and fixed errors in balance calculation. --- src/rpcclient.cpp | 1 + src/rpcwallet.cpp | 23 +++++++++++++-------- src/wallet.cpp | 10 ++++----- src/wallet.h | 52 +++++++++++++++++++++++++++++++++++++---------- 4 files changed, 62 insertions(+), 24 deletions(-) diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 76c99e7c9..ea5ca8e0f 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -40,6 +40,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listreceivedbyaccount", 0 }, { "listreceivedbyaccount", 1 }, { "getbalance", 1 }, + { "getbalance", 2 }, { "getblockhash", 0 }, { "move", 2 }, { "move", 3 }, diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 38e96133b..79b438d41 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -557,7 +557,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) } -int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth) +int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter = MINE_SPENDABLE) { int64_t nBalance = 0; @@ -569,7 +569,7 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi continue; int64_t nReceived, nSent, nFee; - wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee); + wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter); if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth) nBalance += nReceived; @@ -582,18 +582,18 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi return nBalance; } -int64_t GetAccountBalance(const string& strAccount, int nMinDepth) +int64_t GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter = MINE_SPENDABLE) { CWalletDB walletdb(pwalletMain->strWalletFile); - return GetAccountBalance(walletdb, strAccount, nMinDepth); + return GetAccountBalance(walletdb, strAccount, nMinDepth, filter); } Value getbalance(const Array& params, bool fHelp) { - if (fHelp || params.size() > 2) + if (fHelp || params.size() > 3) throw runtime_error( - "getbalance ( \"account\" minconf )\n" + "getbalance ( \"account\" minconf includeWatchonly )\n" "\nIf account is not specified, returns the server's total available balance.\n" "If account is specified, returns the balance in the account.\n" "Note that the account \"\" is not the same as leaving the parameter out.\n" @@ -601,6 +601,7 @@ Value getbalance(const Array& params, bool fHelp) "\nArguments:\n" "1. \"account\" (string, optional) The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n" "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" + "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n" "\nResult:\n" "amount (numeric) The total amount in btc received for this account.\n" "\nExamples:\n" @@ -620,8 +621,14 @@ Value getbalance(const Array& params, bool fHelp) return ValueFromAmount(pwalletMain->GetBalance()); int nMinDepth = 1; + isminefilter filter = MINE_SPENDABLE; if (params.size() > 1) + { nMinDepth = params[1].get_int(); + if(params.size() > 2) + if(params[2].get_bool()) + filter = filter | MINE_WATCH_ONLY; + } if (params[0].get_str() == "*") { // Calculate total balance a different way from GetBalance() @@ -638,7 +645,7 @@ Value getbalance(const Array& params, bool fHelp) string strSentAccount; list > listReceived; list > listSent; - wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount); + wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter); if (wtx.GetDepthInMainChain() >= nMinDepth) { BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listReceived) @@ -653,7 +660,7 @@ Value getbalance(const Array& params, bool fHelp) string strAccount = AccountFromValue(params[0]); - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth); + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, filter); return ValueFromAmount(nBalance); } diff --git a/src/wallet.cpp b/src/wallet.cpp index d4e9fe9d1..3c9aa3306 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -711,7 +711,7 @@ isminetype CWallet::IsMine(const CTxIn &txin) const return MINE_NO; } -int64_t CWallet::GetDebit(const CTxIn &txin) const +int64_t CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const { { LOCK(cs_wallet); @@ -720,7 +720,7 @@ int64_t CWallet::GetDebit(const CTxIn &txin) const { const CWalletTx& prev = (*mi).second; if (txin.prevout.n < prev.vout.size()) - if (IsMine(prev.vout[txin.prevout.n])) + if (IsMine(prev.vout[txin.prevout.n]) & filter) return prev.vout[txin.prevout.n].nValue; } } @@ -801,7 +801,7 @@ void CWalletTx::GetAmounts(list >& listReceived, strSentAccount = strFromAccount; // Compute fee: - int64_t nDebit = GetDebit(); + int64_t nDebit = GetDebit(filter); if (nDebit > 0) // debit>0 means we signed/sent this transaction { int64_t nValueOut = GetValueOut(); @@ -846,7 +846,7 @@ void CWalletTx::GetAmounts(list >& listReceived, } void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived, - int64_t& nSent, int64_t& nFee) const + int64_t& nSent, int64_t& nFee, const isminefilter& filter) const { nReceived = nSent = nFee = 0; @@ -854,7 +854,7 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived, string strSentAccount; list > listReceived; list > listSent; - GetAmounts(listReceived, listSent, allFee, strSentAccount); + GetAmounts(listReceived, listSent, allFee, strSentAccount, filter); if (strAccount == strSentAccount) { diff --git a/src/wallet.h b/src/wallet.h index 355aa3697..b11e6c662 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -288,12 +288,12 @@ public: std::set GetAccountAddresses(std::string strAccount) const; isminetype IsMine(const CTxIn& txin) const; - int64_t GetDebit(const CTxIn& txin) const; + int64_t GetDebit(const CTxIn& txin, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; isminetype IsMine(const CTxOut& txout) const { return ::IsMine(*this, txout.scriptPubKey); } - int64_t GetCredit(const CTxOut& txout, const isminefilter& filter = (MINE_WATCH_ONLY | MINE_SPENDABLE)) const + int64_t GetCredit(const CTxOut& txout, const isminefilter& filter=(MINE_WATCH_ONLY|MINE_SPENDABLE)) const { if (!MoneyRange(txout.nValue)) throw std::runtime_error("CWallet::GetCredit() : value out of range"); @@ -324,12 +324,12 @@ public: return true; return false; } - int64_t GetDebit(const CTransaction& tx) const + int64_t GetDebit(const CTransaction& tx, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const { int64_t nDebit = 0; BOOST_FOREACH(const CTxIn& txin, tx.vin) { - nDebit += GetDebit(txin); + nDebit += GetDebit(txin, filter); if (!MoneyRange(nDebit)) throw std::runtime_error("CWallet::GetDebit() : value out of range"); } @@ -486,6 +486,8 @@ public: mutable bool fCreditCached; mutable bool fImmatureCreditCached; mutable bool fAvailableCreditCached; + mutable bool fWatchDebitCached; + mutable bool fWatchCreditCached; mutable bool fImmatureWatchCreditCached; mutable bool fAvailableWatchCreditCached; mutable bool fChangeCached; @@ -493,6 +495,8 @@ public: mutable int64_t nCreditCached; mutable int64_t nImmatureCreditCached; mutable int64_t nAvailableCreditCached; + mutable int64_t nWatchDebitCached; + mutable int64_t nWatchCreditCached; mutable int64_t nImmatureWatchCreditCached; mutable int64_t nAvailableWatchCreditCached; mutable int64_t nChangeCached; @@ -531,6 +535,8 @@ public: fCreditCached = false; fImmatureCreditCached = false; fAvailableCreditCached = false; + fWatchDebitCached = false; + fWatchCreditCached = false; fImmatureWatchCreditCached = false; fAvailableWatchCreditCached = false; fChangeCached = false; @@ -538,6 +544,8 @@ public: nCreditCached = 0; nImmatureCreditCached = 0; nAvailableCreditCached = 0; + nWatchDebitCached = 0; + nWatchCreditCached = 0; nAvailableWatchCreditCached = 0; nImmatureWatchCreditCached = 0; nChangeCached = 0; @@ -592,6 +600,8 @@ public: { fCreditCached = false; fAvailableCreditCached = false; + fWatchDebitCached = false; + fWatchCreditCached = false; fAvailableWatchCreditCached = false; fImmatureWatchCreditCached = false; fDebitCached = false; @@ -604,15 +614,35 @@ public: MarkDirty(); } - int64_t GetDebit() const + int64_t GetDebit(const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const { if (vin.empty()) return 0; - if (fDebitCached) - return nDebitCached; - nDebitCached = pwallet->GetDebit(*this); - fDebitCached = true; - return nDebitCached; + + int64_t debit = 0; + if(filter & MINE_SPENDABLE) + { + if (fDebitCached) + debit += nDebitCached; + else + { + nDebitCached = pwallet->GetDebit(*this, MINE_SPENDABLE); + fDebitCached = true; + debit += nDebitCached; + } + } + if(filter & MINE_WATCH_ONLY) + { + if(fWatchDebitCached) + debit += nWatchDebitCached; + else + { + nWatchDebitCached = pwallet->GetDebit(*this, MINE_WATCH_ONLY); + fWatchDebitCached = true; + debit += nWatchDebitCached; + } + } + return debit; } int64_t GetCredit(bool fUseCache=true) const @@ -729,7 +759,7 @@ public: std::list >& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, - int64_t& nSent, int64_t& nFee) const; + int64_t& nSent, int64_t& nFee, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; bool IsFromMe() const {