Added argument to getbalance to include watchonly addresses and fixed errors in balance calculation.

This commit is contained in:
JaSK 2014-04-08 15:23:50 +02:00
parent d2692f6116
commit d4640d7d8c
4 changed files with 62 additions and 24 deletions

View file

@ -40,6 +40,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "listreceivedbyaccount", 0 }, { "listreceivedbyaccount", 0 },
{ "listreceivedbyaccount", 1 }, { "listreceivedbyaccount", 1 },
{ "getbalance", 1 }, { "getbalance", 1 },
{ "getbalance", 2 },
{ "getblockhash", 0 }, { "getblockhash", 0 },
{ "move", 2 }, { "move", 2 },
{ "move", 3 }, { "move", 3 },

View file

@ -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; int64_t nBalance = 0;
@ -569,7 +569,7 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi
continue; continue;
int64_t nReceived, nSent, nFee; int64_t nReceived, nSent, nFee;
wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee); wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth) if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
nBalance += nReceived; nBalance += nReceived;
@ -582,18 +582,18 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi
return nBalance; 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); CWalletDB walletdb(pwalletMain->strWalletFile);
return GetAccountBalance(walletdb, strAccount, nMinDepth); return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
} }
Value getbalance(const Array& params, bool fHelp) Value getbalance(const Array& params, bool fHelp)
{ {
if (fHelp || params.size() > 2) if (fHelp || params.size() > 3)
throw runtime_error( 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" "\nIf account is not specified, returns the server's total available balance.\n"
"If account is specified, returns the balance in the account.\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" "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" "\nArguments:\n"
"1. \"account\" (string, optional) The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\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" "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" "\nResult:\n"
"amount (numeric) The total amount in btc received for this account.\n" "amount (numeric) The total amount in btc received for this account.\n"
"\nExamples:\n" "\nExamples:\n"
@ -620,8 +621,14 @@ Value getbalance(const Array& params, bool fHelp)
return ValueFromAmount(pwalletMain->GetBalance()); return ValueFromAmount(pwalletMain->GetBalance());
int nMinDepth = 1; int nMinDepth = 1;
isminefilter filter = MINE_SPENDABLE;
if (params.size() > 1) if (params.size() > 1)
{
nMinDepth = params[1].get_int(); nMinDepth = params[1].get_int();
if(params.size() > 2)
if(params[2].get_bool())
filter = filter | MINE_WATCH_ONLY;
}
if (params[0].get_str() == "*") { if (params[0].get_str() == "*") {
// Calculate total balance a different way from GetBalance() // Calculate total balance a different way from GetBalance()
@ -638,7 +645,7 @@ Value getbalance(const Array& params, bool fHelp)
string strSentAccount; string strSentAccount;
list<pair<CTxDestination, int64_t> > listReceived; list<pair<CTxDestination, int64_t> > listReceived;
list<pair<CTxDestination, int64_t> > listSent; list<pair<CTxDestination, int64_t> > listSent;
wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount); wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
if (wtx.GetDepthInMainChain() >= nMinDepth) if (wtx.GetDepthInMainChain() >= nMinDepth)
{ {
BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listReceived) 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]); string strAccount = AccountFromValue(params[0]);
int64_t nBalance = GetAccountBalance(strAccount, nMinDepth); int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, filter);
return ValueFromAmount(nBalance); return ValueFromAmount(nBalance);
} }

View file

@ -711,7 +711,7 @@ isminetype CWallet::IsMine(const CTxIn &txin) const
return MINE_NO; 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); LOCK(cs_wallet);
@ -720,7 +720,7 @@ int64_t CWallet::GetDebit(const CTxIn &txin) const
{ {
const CWalletTx& prev = (*mi).second; const CWalletTx& prev = (*mi).second;
if (txin.prevout.n < prev.vout.size()) 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; return prev.vout[txin.prevout.n].nValue;
} }
} }
@ -801,7 +801,7 @@ void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& listReceived,
strSentAccount = strFromAccount; strSentAccount = strFromAccount;
// Compute fee: // Compute fee:
int64_t nDebit = GetDebit(); int64_t nDebit = GetDebit(filter);
if (nDebit > 0) // debit>0 means we signed/sent this transaction if (nDebit > 0) // debit>0 means we signed/sent this transaction
{ {
int64_t nValueOut = GetValueOut(); int64_t nValueOut = GetValueOut();
@ -846,7 +846,7 @@ void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& listReceived,
} }
void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived, 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; nReceived = nSent = nFee = 0;
@ -854,7 +854,7 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived,
string strSentAccount; string strSentAccount;
list<pair<CTxDestination, int64_t> > listReceived; list<pair<CTxDestination, int64_t> > listReceived;
list<pair<CTxDestination, int64_t> > listSent; list<pair<CTxDestination, int64_t> > listSent;
GetAmounts(listReceived, listSent, allFee, strSentAccount); GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
if (strAccount == strSentAccount) if (strAccount == strSentAccount)
{ {

View file

@ -288,12 +288,12 @@ public:
std::set<CTxDestination> GetAccountAddresses(std::string strAccount) const; std::set<CTxDestination> GetAccountAddresses(std::string strAccount) const;
isminetype IsMine(const CTxIn& txin) 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 isminetype IsMine(const CTxOut& txout) const
{ {
return ::IsMine(*this, txout.scriptPubKey); 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)) if (!MoneyRange(txout.nValue))
throw std::runtime_error("CWallet::GetCredit() : value out of range"); throw std::runtime_error("CWallet::GetCredit() : value out of range");
@ -324,12 +324,12 @@ public:
return true; return true;
return false; 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; int64_t nDebit = 0;
BOOST_FOREACH(const CTxIn& txin, tx.vin) BOOST_FOREACH(const CTxIn& txin, tx.vin)
{ {
nDebit += GetDebit(txin); nDebit += GetDebit(txin, filter);
if (!MoneyRange(nDebit)) if (!MoneyRange(nDebit))
throw std::runtime_error("CWallet::GetDebit() : value out of range"); throw std::runtime_error("CWallet::GetDebit() : value out of range");
} }
@ -486,6 +486,8 @@ public:
mutable bool fCreditCached; mutable bool fCreditCached;
mutable bool fImmatureCreditCached; mutable bool fImmatureCreditCached;
mutable bool fAvailableCreditCached; mutable bool fAvailableCreditCached;
mutable bool fWatchDebitCached;
mutable bool fWatchCreditCached;
mutable bool fImmatureWatchCreditCached; mutable bool fImmatureWatchCreditCached;
mutable bool fAvailableWatchCreditCached; mutable bool fAvailableWatchCreditCached;
mutable bool fChangeCached; mutable bool fChangeCached;
@ -493,6 +495,8 @@ public:
mutable int64_t nCreditCached; mutable int64_t nCreditCached;
mutable int64_t nImmatureCreditCached; mutable int64_t nImmatureCreditCached;
mutable int64_t nAvailableCreditCached; mutable int64_t nAvailableCreditCached;
mutable int64_t nWatchDebitCached;
mutable int64_t nWatchCreditCached;
mutable int64_t nImmatureWatchCreditCached; mutable int64_t nImmatureWatchCreditCached;
mutable int64_t nAvailableWatchCreditCached; mutable int64_t nAvailableWatchCreditCached;
mutable int64_t nChangeCached; mutable int64_t nChangeCached;
@ -531,6 +535,8 @@ public:
fCreditCached = false; fCreditCached = false;
fImmatureCreditCached = false; fImmatureCreditCached = false;
fAvailableCreditCached = false; fAvailableCreditCached = false;
fWatchDebitCached = false;
fWatchCreditCached = false;
fImmatureWatchCreditCached = false; fImmatureWatchCreditCached = false;
fAvailableWatchCreditCached = false; fAvailableWatchCreditCached = false;
fChangeCached = false; fChangeCached = false;
@ -538,6 +544,8 @@ public:
nCreditCached = 0; nCreditCached = 0;
nImmatureCreditCached = 0; nImmatureCreditCached = 0;
nAvailableCreditCached = 0; nAvailableCreditCached = 0;
nWatchDebitCached = 0;
nWatchCreditCached = 0;
nAvailableWatchCreditCached = 0; nAvailableWatchCreditCached = 0;
nImmatureWatchCreditCached = 0; nImmatureWatchCreditCached = 0;
nChangeCached = 0; nChangeCached = 0;
@ -592,6 +600,8 @@ public:
{ {
fCreditCached = false; fCreditCached = false;
fAvailableCreditCached = false; fAvailableCreditCached = false;
fWatchDebitCached = false;
fWatchCreditCached = false;
fAvailableWatchCreditCached = false; fAvailableWatchCreditCached = false;
fImmatureWatchCreditCached = false; fImmatureWatchCreditCached = false;
fDebitCached = false; fDebitCached = false;
@ -604,15 +614,35 @@ public:
MarkDirty(); MarkDirty();
} }
int64_t GetDebit() const int64_t GetDebit(const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const
{ {
if (vin.empty()) if (vin.empty())
return 0; return 0;
int64_t debit = 0;
if(filter & MINE_SPENDABLE)
{
if (fDebitCached) if (fDebitCached)
return nDebitCached; debit += nDebitCached;
nDebitCached = pwallet->GetDebit(*this); else
{
nDebitCached = pwallet->GetDebit(*this, MINE_SPENDABLE);
fDebitCached = true; fDebitCached = true;
return nDebitCached; 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 int64_t GetCredit(bool fUseCache=true) const
@ -729,7 +759,7 @@ public:
std::list<std::pair<CTxDestination, int64_t> >& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; std::list<std::pair<CTxDestination, int64_t> >& 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, 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 bool IsFromMe() const
{ {