Fixes #1345 so that UTXO debit and credits are computed correctly for a transaction.

This commit is contained in:
Simon
2016-09-20 16:22:30 -07:00
parent 2f15f588b2
commit 86cf60b5c8
2 changed files with 178 additions and 7 deletions

View File

@@ -1328,6 +1328,7 @@ int CWalletTx::GetRequestCount() const
return nRequests;
}
// GetAmounts will determine the transparent debits and credits for a given wallet tx.
void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
list<COutputEntry>& listSent, CAmount& nFee, string& strSentAccount, const isminefilter& filter) const
{
@@ -1336,12 +1337,77 @@ void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
listSent.clear();
strSentAccount = strFromAccount;
// Compute fee:
// Is this tx sent/signed by me?
CAmount nDebit = GetDebit(filter);
if (nDebit > 0) // debit>0 means we signed/sent this transaction
{
CAmount nValueOut = GetValueOut();
nFee = nDebit - nValueOut;
bool isFromMyTaddr = nDebit > 0; // debit>0 means we signed/sent this transaction
// Does this tx spend my notes?
bool isFromMyZaddr = false;
for (const JSDescription& js : vjoinsplit) {
for (const uint256& nullifier : js.nullifiers) {
if (pwallet->IsFromMe(nullifier)) {
isFromMyZaddr = true;
break;
}
}
if (isFromMyZaddr) {
break;
}
}
// Compute fee if we sent this transaction.
if (isFromMyTaddr) {
CAmount nValueOut = GetValueOut(); // transparent outputs plus all vpub_old
CAmount nValueIn = 0;
for (const JSDescription & js : vjoinsplit) {
nValueIn += js.vpub_new;
}
nFee = nDebit - nValueOut + nValueIn;
}
// Create output entry for vpub_old/new, if we sent utxos from this transaction
if (isFromMyTaddr) {
CAmount myVpubOld = 0;
CAmount myVpubNew = 0;
for (const JSDescription& js : vjoinsplit) {
bool fMyJSDesc = false;
// Check input side
for (const uint256& nullifier : js.nullifiers) {
if (pwallet->IsFromMe(nullifier)) {
fMyJSDesc = true;
break;
}
}
// Check output side
if (!fMyJSDesc) {
for (const std::pair<JSOutPoint, CNoteData> nd : this->mapNoteData) {
if (nd.first.js < vjoinsplit.size() && nd.first.n < vjoinsplit[nd.first.js].ciphertexts.size()) {
fMyJSDesc = true;
break;
}
}
}
if (fMyJSDesc) {
myVpubOld += js.vpub_old;
myVpubNew += js.vpub_new;
}
if (!MoneyRange(js.vpub_old) || !MoneyRange(js.vpub_new) || !MoneyRange(myVpubOld) || !MoneyRange(myVpubNew)) {
throw std::runtime_error("CWalletTx::GetAmounts: value out of range");
}
}
// Create an output for the value taken from or added to the transparent value pool by JoinSplits
if (myVpubOld > myVpubNew) {
COutputEntry output = {CNoDestination(), myVpubOld - myVpubNew, (int)vout.size()};
listSent.push_back(output);
} else if (myVpubNew > myVpubOld) {
COutputEntry output = {CNoDestination(), myVpubNew - myVpubOld, (int)vout.size()};
listReceived.push_back(output);
}
}
// Sent/received.