mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-21 07:39:08 +01:00
Merge pull request #4045
a3e192areplaced MINE_ with ISMINE_ (JaSK)53a2148fixed bug where validateaddress doesn't display information (JaSK)f28707afixed bug in ListReceived() (JaSK)519dd1cAdded MINE_ALL = (spendable|watchonly) (JaSK)23b0506Fixed some stuff in TransactionDesc (JaSK)80dda36removed default argument values for ismine filter (JaSK)d5087d1Use script matching rather than destination matching for watch-only. (Pieter Wuille)0fa2f88added includedWatchonly argument to listreceivedbyaddress/...account (JaSK)f87ba3dadded includeWatchonly argument to 'gettransaction' because it affects balance calculation (JaSK)a5c6c5dfixed tiny glitch and improved readability like laanwj suggested (JaSK)d7d5d23Added argument to listtransactions and listsinceblock to include watchonly addresses (JaSK)952877eShowing 'involvesWatchonly' property for transactions returned by 'listtransactions' and 'listsinceblock'. It is only appended when the transaction involves a watchonly address. (JaSK)83f3543Added argument to listaccounts to include watchonly addresses (JaSK)d4640d7Added argument to getbalance to include watchonly addresses and fixed errors in balance calculation. (JaSK)d2692f6Watchonly transactions are marked in transaction history (JaSK)ffd40daWatchonly balances are shown separately in gui. (JaSK)2935b21qt: Hide unspendable outputs in coin control (Wladimir J. van der Laan)c898846Add support for watch-only addresses (Pieter Wuille)
This commit is contained in:
113
src/wallet.cpp
113
src/wallet.cpp
@@ -149,6 +149,21 @@ bool CWallet::LoadCScript(const CScript& redeemScript)
|
||||
return CCryptoKeyStore::AddCScript(redeemScript);
|
||||
}
|
||||
|
||||
bool CWallet::AddWatchOnly(const CScript &dest)
|
||||
{
|
||||
if (!CCryptoKeyStore::AddWatchOnly(dest))
|
||||
return false;
|
||||
nTimeFirstKey = 1; // No birthday information for watch-only keys.
|
||||
if (!fFileBacked)
|
||||
return true;
|
||||
return CWalletDB(strWalletFile).WriteWatchOnly(dest);
|
||||
}
|
||||
|
||||
bool CWallet::LoadWatchOnly(const CScript &dest)
|
||||
{
|
||||
return CCryptoKeyStore::AddWatchOnly(dest);
|
||||
}
|
||||
|
||||
bool CWallet::Unlock(const SecureString& strWalletPassphrase)
|
||||
{
|
||||
CCrypter crypter;
|
||||
@@ -684,7 +699,7 @@ void CWallet::EraseFromWallet(const uint256 &hash)
|
||||
}
|
||||
|
||||
|
||||
bool CWallet::IsMine(const CTxIn &txin) const
|
||||
isminetype CWallet::IsMine(const CTxIn &txin) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
@@ -693,14 +708,13 @@ bool CWallet::IsMine(const CTxIn &txin) const
|
||||
{
|
||||
const CWalletTx& prev = (*mi).second;
|
||||
if (txin.prevout.n < prev.vout.size())
|
||||
if (IsMine(prev.vout[txin.prevout.n]))
|
||||
return true;
|
||||
return IsMine(prev.vout[txin.prevout.n]);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return ISMINE_NO;
|
||||
}
|
||||
|
||||
int64_t CWallet::GetDebit(const CTxIn &txin) const
|
||||
int64_t CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
|
||||
{
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
@@ -709,7 +723,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;
|
||||
}
|
||||
}
|
||||
@@ -718,17 +732,19 @@ int64_t CWallet::GetDebit(const CTxIn &txin) const
|
||||
|
||||
bool CWallet::IsChange(const CTxOut& txout) const
|
||||
{
|
||||
CTxDestination address;
|
||||
|
||||
// TODO: fix handling of 'change' outputs. The assumption is that any
|
||||
// payment to a TX_PUBKEYHASH that is mine but isn't in the address book
|
||||
// payment to a script that is ours, but is not in the address book
|
||||
// is change. That assumption is likely to break when we implement multisignature
|
||||
// wallets that return change back into a multi-signature-protected address;
|
||||
// a better way of identifying which outputs are 'the send' and which are
|
||||
// 'the change' will need to be implemented (maybe extend CWalletTx to remember
|
||||
// which output, if any, was change).
|
||||
if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address))
|
||||
if (::IsMine(*this, txout.scriptPubKey))
|
||||
{
|
||||
CTxDestination address;
|
||||
if (!ExtractDestination(txout.scriptPubKey, address))
|
||||
return true;
|
||||
|
||||
LOCK(cs_wallet);
|
||||
if (!mapAddressBook.count(address))
|
||||
return true;
|
||||
@@ -782,7 +798,7 @@ int CWalletTx::GetRequestCount() const
|
||||
}
|
||||
|
||||
void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& listReceived,
|
||||
list<pair<CTxDestination, int64_t> >& listSent, int64_t& nFee, string& strSentAccount) const
|
||||
list<pair<CTxDestination, int64_t> >& listSent, int64_t& nFee, string& strSentAccount, const isminefilter& filter) const
|
||||
{
|
||||
nFee = 0;
|
||||
listReceived.clear();
|
||||
@@ -790,7 +806,7 @@ void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& 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();
|
||||
@@ -800,7 +816,8 @@ void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& listReceived,
|
||||
// Sent/received.
|
||||
BOOST_FOREACH(const CTxOut& txout, vout)
|
||||
{
|
||||
bool fIsMine;
|
||||
isminetype fIsMine = pwallet->IsMine(txout);
|
||||
|
||||
// Only need to handle txouts if AT LEAST one of these is true:
|
||||
// 1) they debit from us (sent)
|
||||
// 2) the output is to us (received)
|
||||
@@ -809,9 +826,8 @@ void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& listReceived,
|
||||
// Don't report 'change' txouts
|
||||
if (pwallet->IsChange(txout))
|
||||
continue;
|
||||
fIsMine = pwallet->IsMine(txout);
|
||||
}
|
||||
else if (!(fIsMine = pwallet->IsMine(txout)))
|
||||
else if (!(fIsMine & filter))
|
||||
continue;
|
||||
|
||||
// In either case, we need to get the destination address
|
||||
@@ -835,7 +851,7 @@ void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& 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;
|
||||
|
||||
@@ -843,7 +859,7 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived,
|
||||
string strSentAccount;
|
||||
list<pair<CTxDestination, int64_t> > listReceived;
|
||||
list<pair<CTxDestination, int64_t> > listSent;
|
||||
GetAmounts(listReceived, listSent, allFee, strSentAccount);
|
||||
GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
|
||||
|
||||
if (strAccount == strSentAccount)
|
||||
{
|
||||
@@ -1055,7 +1071,52 @@ int64_t CWallet::GetImmatureBalance() const
|
||||
return nTotal;
|
||||
}
|
||||
|
||||
// populate vCoins with vector of spendable COutputs
|
||||
int64_t CWallet::GetWatchOnlyBalance() const
|
||||
{
|
||||
int64_t nTotal = 0;
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
{
|
||||
const CWalletTx* pcoin = &(*it).second;
|
||||
if (pcoin->IsTrusted())
|
||||
nTotal += pcoin->GetAvailableWatchOnlyCredit();
|
||||
}
|
||||
}
|
||||
|
||||
return nTotal;
|
||||
}
|
||||
|
||||
int64_t CWallet::GetUnconfirmedWatchOnlyBalance() const
|
||||
{
|
||||
int64_t nTotal = 0;
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
{
|
||||
const CWalletTx* pcoin = &(*it).second;
|
||||
if (!IsFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
|
||||
nTotal += pcoin->GetAvailableWatchOnlyCredit();
|
||||
}
|
||||
}
|
||||
return nTotal;
|
||||
}
|
||||
|
||||
int64_t CWallet::GetImmatureWatchOnlyBalance() const
|
||||
{
|
||||
int64_t nTotal = 0;
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||
{
|
||||
const CWalletTx* pcoin = &(*it).second;
|
||||
nTotal += pcoin->GetImmatureWatchOnlyCredit();
|
||||
}
|
||||
}
|
||||
return nTotal;
|
||||
}
|
||||
|
||||
// populate vCoins with vector of available COutputs.
|
||||
void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const
|
||||
{
|
||||
vCoins.clear();
|
||||
@@ -1081,10 +1142,11 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const
|
||||
continue;
|
||||
|
||||
for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
|
||||
if (!(IsSpent(wtxid, i)) && IsMine(pcoin->vout[i]) &&
|
||||
isminetype mine = IsMine(pcoin->vout[i]);
|
||||
if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO &&
|
||||
!IsLockedCoin((*it).first, i) && pcoin->vout[i].nValue > 0 &&
|
||||
(!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i)))
|
||||
vCoins.push_back(COutput(pcoin, i, nDepth));
|
||||
vCoins.push_back(COutput(pcoin, i, nDepth, mine & ISMINE_SPENDABLE));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1151,11 +1213,14 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT
|
||||
|
||||
random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
|
||||
|
||||
BOOST_FOREACH(COutput output, vCoins)
|
||||
BOOST_FOREACH(const COutput &output, vCoins)
|
||||
{
|
||||
if (!output.fSpendable)
|
||||
continue;
|
||||
|
||||
const CWalletTx *pcoin = output.tx;
|
||||
|
||||
if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
|
||||
if (output.nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? nConfMine : nConfTheirs))
|
||||
continue;
|
||||
|
||||
int i = output.i;
|
||||
@@ -1244,6 +1309,8 @@ bool CWallet::SelectCoins(int64_t nTargetValue, set<pair<const CWalletTx*,unsign
|
||||
{
|
||||
BOOST_FOREACH(const COutput& out, vCoins)
|
||||
{
|
||||
if(!out.fSpendable)
|
||||
continue;
|
||||
nValueRet += out.tx->vout[out.i].nValue;
|
||||
setCoinsRet.insert(make_pair(out.tx, out.i));
|
||||
}
|
||||
@@ -1804,7 +1871,7 @@ std::map<CTxDestination, int64_t> CWallet::GetAddressBalances()
|
||||
continue;
|
||||
|
||||
int nDepth = pcoin->GetDepthInMainChain();
|
||||
if (nDepth < (pcoin->IsFromMe() ? 0 : 1))
|
||||
if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1))
|
||||
continue;
|
||||
|
||||
for (unsigned int i = 0; i < pcoin->vout.size(); i++)
|
||||
|
||||
Reference in New Issue
Block a user