Skip to content

Commit

Permalink
Keep track of wallet UTXOs and use them for PS balances and rounds ca…
Browse files Browse the repository at this point in the history
…lculations (#1655)

* keep track of wallet UTXOs and use them for PS balances and rounds calculations

* fix
  • Loading branch information
UdjinM6 authored Sep 27, 2017
1 parent 0c1679e commit 8e9289e
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 60 deletions.
4 changes: 2 additions & 2 deletions src/privatesend-client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1214,7 +1214,7 @@ bool CPrivateSendClient::MakeCollateralAmounts(const CompactTallyItem& tallyItem
coinControl.fAllowOtherInputs = false;
coinControl.fAllowWatchOnly = false;
// send change to the same address so that we were able create more denoms out of it later
coinControl.destChange = tallyItem.address.Get();
coinControl.destChange = tallyItem.txdest;
BOOST_FOREACH(const CTxIn& txin, tallyItem.vecTxIn)
coinControl.Select(txin.prevout);

Expand Down Expand Up @@ -1350,7 +1350,7 @@ bool CPrivateSendClient::CreateDenominated(const CompactTallyItem& tallyItem, bo
coinControl.fAllowOtherInputs = false;
coinControl.fAllowWatchOnly = false;
// send change to the same address so that we were able create more denoms out of it later
coinControl.destChange = tallyItem.address.Get();
coinControl.destChange = tallyItem.txdest;
BOOST_FOREACH(const CTxIn& txin, tallyItem.vecTxIn)
coinControl.Select(txin.prevout);

Expand Down
123 changes: 66 additions & 57 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,7 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
{
mapTxSpends.insert(make_pair(outpoint, wtxid));
setWalletUTXO.erase(outpoint);

pair<TxSpends::iterator, TxSpends::iterator> range;
range = mapTxSpends.equal_range(outpoint);
Expand Down Expand Up @@ -955,6 +956,11 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
wtxIn.hashBlock.ToString());
}
AddToSpends(hash);
for(int i = 0; i < wtx.vout.size(); ++i) {
if (IsMine(wtx.vout[i]) && !IsSpent(hash, i)) {
setWalletUTXO.insert(COutPoint(hash, i));
}
}
}

bool fUpdated = false;
Expand Down Expand Up @@ -2173,14 +2179,18 @@ CAmount CWallet::GetAnonymizedBalance() const
if(fLiteMode) return 0;

CAmount nTotal = 0;
{
LOCK2(cs_main, 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->GetAnonymizedCredit();
LOCK2(cs_main, cs_wallet);

std::set<uint256> setWalletTxesCounted;
for (auto& outpoint : setWalletUTXO) {

if (setWalletTxesCounted.find(outpoint.hash) != setWalletTxesCounted.end()) continue;
setWalletTxesCounted.insert(outpoint.hash);

for (map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash); it != mapWallet.end() && it->first == outpoint.hash; ++it) {
if (it->second.IsTrusted())
nTotal += it->second.GetAnonymizedCredit();
}
}

Expand All @@ -2196,24 +2206,12 @@ float CWallet::GetAverageAnonymizedRounds() const
int nTotal = 0;
int nCount = 0;

{
LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;

uint256 hash = (*it).first;

for (unsigned int i = 0; i < pcoin->vout.size(); i++) {

COutPoint outpoint = COutPoint(hash, i);

if(IsSpent(hash, i) || IsMine(pcoin->vout[i]) != ISMINE_SPENDABLE || !IsDenominated(outpoint)) continue;
LOCK2(cs_main, cs_wallet);
for (auto& outpoint : setWalletUTXO) {
if(!IsDenominated(outpoint)) continue;

nTotal += GetOutpointPrivateSendRounds(outpoint);
nCount++;
}
}
nTotal += GetOutpointPrivateSendRounds(outpoint);
nCount++;
}

if(nCount == 0) return 0;
Expand All @@ -2229,25 +2227,15 @@ CAmount CWallet::GetNormalizedAnonymizedBalance() const

CAmount nTotal = 0;

{
LOCK2(cs_main, cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;

uint256 hash = (*it).first;

for (unsigned int i = 0; i < pcoin->vout.size(); i++) {

COutPoint outpoint = COutPoint(hash, i);

if(IsSpent(hash, i) || IsMine(pcoin->vout[i]) != ISMINE_SPENDABLE || !IsDenominated(outpoint)) continue;
if (pcoin->GetDepthInMainChain() < 0) continue;
LOCK2(cs_main, cs_wallet);
for (auto& outpoint : setWalletUTXO) {
map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash);
if (it == mapWallet.end()) continue;
if (!IsDenominated(outpoint)) continue;
if (it->second.GetDepthInMainChain() < 0) continue;

int nRounds = GetOutpointPrivateSendRounds(outpoint);
nTotal += pcoin->vout[i].nValue * nRounds / privateSendClient.nPrivateSendRounds;
}
}
int nRounds = GetOutpointPrivateSendRounds(outpoint);
nTotal += it->second.vout[outpoint.n].nValue * nRounds / privateSendClient.nPrivateSendRounds;
}

return nTotal;
Expand Down Expand Up @@ -2858,21 +2846,29 @@ bool CWallet::SelectCoinsGrouppedByAddresses(std::vector<CompactTallyItem>& vecT
CAmount nSmallestDenom = CPrivateSend::GetSmallestDenomination();

// Tally
map<CBitcoinAddress, CompactTallyItem> mapTally;
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) {
map<CTxDestination, CompactTallyItem> mapTally;
std::set<uint256> setWalletTxesCounted;
for (auto& outpoint : setWalletUTXO) {

if (setWalletTxesCounted.find(outpoint.hash) != setWalletTxesCounted.end()) continue;
setWalletTxesCounted.insert(outpoint.hash);

map<uint256, CWalletTx>::const_iterator it = mapWallet.find(outpoint.hash);
if (it == mapWallet.end()) continue;

const CWalletTx& wtx = (*it).second;

if(wtx.IsCoinBase() && wtx.GetBlocksToMaturity() > 0) continue;
if(fSkipUnconfirmed && !wtx.IsTrusted()) continue;

for (unsigned int i = 0; i < wtx.vout.size(); i++) {
CTxDestination address;
if (!ExtractDestination(wtx.vout[i].scriptPubKey, address)) continue;
CTxDestination txdest;
if (!ExtractDestination(wtx.vout[i].scriptPubKey, txdest)) continue;

isminefilter mine = ::IsMine(*this, address);
isminefilter mine = ::IsMine(*this, txdest);
if(!(mine & filter)) continue;

if(IsSpent(wtx.GetHash(), i) || IsLockedCoin(wtx.GetHash(), i)) continue;
if(IsSpent(outpoint.hash, i) || IsLockedCoin(outpoint.hash, i)) continue;

if(fSkipDenominated && IsDenominatedAmount(wtx.vout[i].nValue)) continue;

Expand All @@ -2884,19 +2880,19 @@ bool CWallet::SelectCoinsGrouppedByAddresses(std::vector<CompactTallyItem>& vecT
// otherwise they will just lead to higher fee / lower priority
if(wtx.vout[i].nValue <= nSmallestDenom/10) continue;
// ignore anonymized
if(GetOutpointPrivateSendRounds(COutPoint(wtx.GetHash(), i)) >= privateSendClient.nPrivateSendRounds) continue;
if(GetOutpointPrivateSendRounds(COutPoint(outpoint.hash, i)) >= privateSendClient.nPrivateSendRounds) continue;
}

CompactTallyItem& item = mapTally[address];
item.address = address;
CompactTallyItem& item = mapTally[txdest];
item.txdest = txdest;
item.nAmount += wtx.vout[i].nValue;
item.vecTxIn.push_back(CTxIn(wtx.GetHash(), i));
item.vecTxIn.push_back(CTxIn(outpoint.hash, i));
}
}

// construct resulting vector
vecTallyRet.clear();
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CompactTallyItem)& item, mapTally) {
BOOST_FOREACH(const PAIRTYPE(CTxDestination, CompactTallyItem)& item, mapTally) {
if(fAnonymizable && item.second.nAmount < nSmallestDenom) continue;
vecTallyRet.push_back(item.second);
}
Expand All @@ -2916,10 +2912,12 @@ bool CWallet::SelectCoinsGrouppedByAddresses(std::vector<CompactTallyItem>& vecT
}

// debug
std::string strMessage = "SelectCoinsGrouppedByAddresses - vecTallyRet:\n";
BOOST_FOREACH(CompactTallyItem& item, vecTallyRet)
strMessage += strprintf(" %s %f\n", item.address.ToString().c_str(), float(item.nAmount)/COIN);
LogPrint("selectcoins", "%s", strMessage);
if (LogAcceptCategory("selectcoins")) {
std::string strMessage = "SelectCoinsGrouppedByAddresses - vecTallyRet:\n";
BOOST_FOREACH(CompactTallyItem& item, vecTallyRet)
strMessage += strprintf(" %s %f\n", CBitcoinAddress(item.txdest).ToString().c_str(), float(item.nAmount)/COIN);
LogPrint("selectcoins", "%s", strMessage);
}

return vecTallyRet.size() > 0;
}
Expand Down Expand Up @@ -3630,6 +3628,17 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
}
}

{
LOCK2(cs_main, cs_wallet);
for (auto& pair : mapWallet) {
for(int i = 0; i < pair.second.vout.size(); ++i) {
if (IsMine(pair.second.vout[i]) && !IsSpent(pair.first, i)) {
setWalletUTXO.insert(COutPoint(pair.first, i));
}
}
}
}

if (nLoadWalletRet != DB_LOAD_OK)
return nLoadWalletRet;
fFirstRunRet = !vchDefaultKey.IsValid();
Expand Down
4 changes: 3 additions & 1 deletion src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ enum AvailableCoinsType

struct CompactTallyItem
{
CBitcoinAddress address;
CTxDestination txdest;
CAmount nAmount;
std::vector<CTxIn> vecTxIn;
CompactTallyItem()
Expand Down Expand Up @@ -651,6 +651,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
void AddToSpends(const COutPoint& outpoint, const uint256& wtxid);
void AddToSpends(const uint256& wtxid);

std::set<COutPoint> setWalletUTXO;

/* Mark a transaction (and its in-wallet descendants) as conflicting with a particular block. */
void MarkConflicted(const uint256& hashBlock, const uint256& hashTx);

Expand Down

0 comments on commit 8e9289e

Please sign in to comment.