Deal better with unknown amounts in balances

This commit is contained in:
Pieter Wuille 2016-02-16 04:07:00 +01:00
parent df4c512ded
commit 27d32fc6a7

View file

@ -757,7 +757,7 @@ CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
const CWalletTx& prev = (*mi).second;
if (txin.prevout.n < prev.vout.size())
if (IsMine(prev.vout[txin.prevout.n]) & filter)
return prev.GetValueOut(txin.prevout.n);
return std::max<CAmount>(0, prev.GetValueOut(txin.prevout.n));
}
}
return 0;
@ -867,11 +867,21 @@ void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
if (nDebit > 0) // debit>0 means we signed/sent this transaction
nFee = nTxFee;
CTxDestination addressUnaccounted = CNoDestination();
int voutUnaccounted = -1;
CAmount nValueUnaccounted = nDebit - nFee;
int nUnaccountedOutputs = 0;
// Sent/received.
for (unsigned int i = 0; i < vout.size(); ++i)
{
CAmount nValueOut = GetValueOut(i);
if (nValueOut >= 0) {
nValueUnaccounted -= nValueOut;
}
const CTxOut& txout = vout[i];
isminetype fIsMine = pwallet->IsMine(txout);
isminetype fIsMine = nValueOut >= 0 ? pwallet->IsMine(txout) : ISMINE_NO;
// 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)
@ -893,12 +903,18 @@ void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
address = CNoDestination();
}
COutputEntry output = {address, GetValueOut(i), (int)i, CPubKey()};
if (!txout.nValue.IsAmount() && GetValueOut(i) > 0) {
output.confidentiality_pubkey = GetBlindingKey(i);
if (nDebit > 0 && nValueOut < 0) {
// This is an output we'd add to listSent, but we don't know its value.
// Instead just remember its details so we can reconstruct it or
// correct for it afterwards.
addressUnaccounted = address;
voutUnaccounted = i;
nUnaccountedOutputs++;
continue;
}
COutputEntry output = {address, nValueOut, (int)i, GetBlindingKey(i)};
// If we are debited by the transaction, add the output as a "sent" entry
if (nDebit > 0)
listSent.push_back(output);
@ -908,6 +924,17 @@ void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
listReceived.push_back(output);
}
if (nValueUnaccounted != 0 && nDebit > 0) {
if (nValueUnaccounted > 0 && nUnaccountedOutputs == 1) {
// There is exactly one sent output with unknown value. Reconstruct it.
COutputEntry unaccounted = {addressUnaccounted, nValueUnaccounted, voutUnaccounted, CPubKey()};
listSent.push_back(unaccounted);
} else {
// It's not simple. Create a synthetic unknown output entry to correct.
COutputEntry unaccounted = {CNoDestination(), nValueUnaccounted, -1, CPubKey()};
listSent.push_back(unaccounted);
}
}
}
void CWalletTx::GetAccountAmounts(const string& strAccount, CAmount& nReceived,