diff --git a/src/darksend.cpp b/src/darksend.cpp index 4d7de9f88a0f..770360a4f3f8 100644 --- a/src/darksend.cpp +++ b/src/darksend.cpp @@ -1415,66 +1415,77 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready) // ** find the coins we'll use std::vector vCoins; - int64 nValueMin = 0.01*COIN; - int64 nValueMax = DARKSEND_POOL_MAX; + int64 nValueMin = 0.1*COIN + 1; // select at least one smallest denom int64 nValueIn = 0; int minRounds = -2; //non denominated funds are rounds of less than 0 - int maxRounds = 2; - int maxAmount = DARKSEND_POOL_MAX/COIN; + int maxRounds = 0; + int64 balance = pwalletMain->GetBalance(); + int64 balanceNeedsDenominated = nAnonymizeDarkcoinAmount*COIN; // set target value on init + int64 balanceNeedsAnonymized = nAnonymizeDarkcoinAmount*COIN; // set target value on init bool hasFeeInput = false; - // if we have more denominated funds (of any maturity) than the nAnonymizeDarkcoinAmount, we should use use those - if(pwalletMain->GetDenominatedBalance(true) >= nAnonymizeDarkcoinAmount*COIN || - pwalletMain->GetDenominatedBalance(true) >= pwalletMain->GetBalance()*.9) { + // do we have enough balance? + if(balanceNeedsDenominated > balance) balanceNeedsDenominated = balance; + if(balanceNeedsAnonymized > balance) balanceNeedsAnonymized = balance; + + // count in what is already done + balanceNeedsDenominated -= pwalletMain->GetDenominatedBalance(true); + balanceNeedsAnonymized -= pwalletMain->GetAnonymizedBalance(); + + // is there anything left to do? + // if no more denomination needed do not select non-denom inputs + if(balanceNeedsDenominated <= 0) { minRounds = 0; maxRounds = nDarksendRounds; } - //if we're set to less than a thousand, don't submit for than that to the pool - if(nAnonymizeDarkcoinAmount < DARKSEND_POOL_MAX/COIN) maxAmount = nAnonymizeDarkcoinAmount; - int64 balanceNeedsAnonymized = pwalletMain->GetBalance() - pwalletMain->GetAnonymizedBalance(); - if(balanceNeedsAnonymized > maxAmount*COIN) balanceNeedsAnonymized= maxAmount*COIN; - if(balanceNeedsAnonymized < COIN*2.5 || - (vecDisabledDenominations.size() > 0 && balanceNeedsAnonymized < COIN*12.5)){ - LogPrintf("DoAutomaticDenominating : No funds detected in need of denominating \n"); + // is amount to anonymize still higher then pool allows? + if(balanceNeedsAnonymized > DARKSEND_POOL_MAX) balanceNeedsAnonymized = DARKSEND_POOL_MAX; + + // if there is nothing more to anonymize + if(balanceNeedsAnonymized <= 1*COIN){ + LogPrintf("DoAutomaticDenominating : No funds detected in need of anonymizing \n"); return false; } - // if the balance is more the pool max, take the pool max - if(balanceNeedsAnonymized > nValueMax) { - balanceNeedsAnonymized = nValueMax; - } // select coins that should be given to the pool - if (!pwalletMain->SelectCoinsDark(nValueMin, maxAmount*COIN, vCoins, nValueIn, minRounds, maxRounds, hasFeeInput)) + if (!pwalletMain->SelectCoinsDark(nValueMin, balanceNeedsAnonymized, vCoins, nValueIn, minRounds, maxRounds, hasFeeInput)) { - nValueIn = 0; - vCoins.clear(); - - // look for inputs larger than the max amount, if we find anything we need to split it up - if (pwalletMain->SelectCoinsDark(maxAmount*COIN, 9999999*COIN, vCoins, nValueIn, minRounds, maxRounds, hasFeeInput)) + // fall back to non-denom + minRounds = -2; + maxRounds = 0; + if (!pwalletMain->SelectCoinsDark(nValueMin, balanceNeedsAnonymized, vCoins, nValueIn, minRounds, maxRounds, hasFeeInput)) { - if(!fDryRun) SplitUpMoney(); - return true; - } + nValueIn = 0; + vCoins.clear(); - LogPrintf("DoAutomaticDenominating : No funds detected in need of denominating (2)\n"); - return false; + // look for inputs larger than the max amount, if we find anything we need to split it up + if (pwalletMain->SelectCoinsDark(balanceNeedsAnonymized, 9999999*COIN, vCoins, nValueIn, minRounds, maxRounds, hasFeeInput)) + { + if(!fDryRun) SplitUpMoney(); + return true; + } + + LogPrintf("DoAutomaticDenominating : No funds detected in need of denominating \n"); + return false; + } } - // the darksend pool can only take 2.5DRK minimum - if(nValueIn < COIN*2.5 || - (vecDisabledDenominations.size() > 0 && nValueIn < COIN*12.5) - ){ - //simply look for non-denominated coins - if (pwalletMain->SelectCoinsDark(maxAmount*COIN, 9999999*COIN, vCoins, nValueIn, minRounds, maxRounds, hasFeeInput)) - { - if(!fDryRun) SplitUpMoney(); - return true; + if(vecDisabledDenominations.size() == 0){ + //if we have 20x 0.1DRk and 1DRK inputs, we can start just anonymizing 10DRK and 100DRK inputs only. + if(pwalletMain->CountInputsWithAmount((1 * COIN)+1) >= 20 && + pwalletMain->CountInputsWithAmount((.1 * COIN)+1) >= 20){ + vecDisabledDenominations.push_back((1 * COIN)+1); + vecDisabledDenominations.push_back((.1 * COIN)+1); } + } - LogPrintf("DoAutomaticDenominating : Too little to denominate \n"); - return false; + // but if we tried to split last time and didn't find anything + // then this time we'll fall back to 1s and 0.1s to complete anonymization + if(nValueIn < 10*COIN){ + vecDisabledDenominations.clear(); + LogPrintf("DoAutomaticDenominating : falling back to 0.1s and 1s\n"); } //check to see if we have the fee sized inputs, it requires these @@ -1485,15 +1496,6 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready) if(fDryRun) return true; - if(vecDisabledDenominations.size() == 0){ - //if we have 20x 0.1DRk and 1DRK inputs, we can start just anonymizing 10DRK inputs. - if(pwalletMain->CountInputsWithAmount((1 * COIN)+1) >= 20 && - pwalletMain->CountInputsWithAmount((.1 * COIN)+1) >= 20){ - vecDisabledDenominations.push_back((1 * COIN)+1); - vecDisabledDenominations.push_back((.1 * COIN)+1); - } - } - // initial phase, find a masternode if(!sessionFoundMasternode){ int nUseQueue = rand()%100; @@ -1502,10 +1504,10 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready) //randomize the amounts we mix // if we have minRounds set, or if our non-demon is less than 5% of denom coins - if(minRounds == 0 || + if(minRounds == 0 || pwalletMain->GetDenominatedBalance(true) * 0.05 > pwalletMain->GetDenominatedBalance(false)) { for(int a = 0; a < 10; a++){ //try 10 amounts and see if we match a queue - int r = (rand()%(maxAmount-(nValueMin/COIN)))+(nValueMin/COIN); + int r = (rand()%((balanceNeedsAnonymized-nValueMin)/COIN))+(nValueMin/COIN); vCoins.clear(); nValueIn = 0; @@ -1533,7 +1535,7 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready) } } } - if(sessionTotalValue > maxAmount*COIN) sessionTotalValue = maxAmount*COIN; + if(sessionTotalValue > balanceNeedsAnonymized) sessionTotalValue = balanceNeedsAnonymized; double fDarkcoinSubmitted = sessionTotalValue / COIN; @@ -1544,6 +1546,16 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready) return false; } + if(minRounds >= 0){ + //use same denominations + std::vector vecAmounts; + pwalletMain->ConvertList(vCoins, vecAmounts); + sessionDenom = GetDenominationsByAmounts(vecAmounts); + } else { + //use all possible denominations + sessionDenom = GetDenominationsByAmount(sessionTotalValue); + } + //don't use the queues all of the time for mixing if(nUseQueue > 33){ @@ -1566,8 +1578,8 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready) } // If we don't match the denominations, we don't want to submit our inputs - if(dsq.nDenom != GetDenominationsByAmount(sessionTotalValue)) { - if(fDebug) LogPrintf(" dsq.nDenom != GetDenominationsByAmount %d %d \n", dsq.nDenom, GetDenominationsByAmount(sessionTotalValue)); + if(dsq.nDenom != sessionDenom) { + if(fDebug) LogPrintf(" dsq.nDenom != GetDenominationsByAmount %d %d \n", dsq.nDenom, sessionDenom); continue; } dsq.time = 0; //remove node @@ -1590,16 +1602,6 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready) vecMasternodesUsed.push_back(dsq.vin); - if(minRounds >= 0){ - //use same denominations - std::vector vecAmounts; - pwalletMain->ConvertList(vCoins, vecAmounts); - sessionDenom = GetDenominationsByAmounts(vecAmounts); - } else { - //use all possible denominations - sessionDenom = GetDenominationsByAmount(sessionTotalValue); - } - pnode->PushMessage("dsa", sessionDenom, txCollateral); LogPrintf("DoAutomaticDenominating --- connected (from queue), sending dsa for %d %d - %s\n", sessionDenom, GetDenominationsByAmount(sessionTotalValue), pnode->addr.ToString().c_str()); return true; @@ -1652,16 +1654,6 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready) vecMasternodesUsed.push_back(darkSendMasterNodes[i].vin); - if(minRounds >= 0){ - //use same denominations - std::vector vecAmounts; - pwalletMain->ConvertList(vCoins, vecAmounts); - sessionDenom = GetDenominationsByAmounts(vecAmounts); - } else { - //use all possible denominations - sessionDenom = GetDenominationsByAmount(sessionTotalValue); - } - pnode->PushMessage("dsa", sessionDenom, txCollateral); LogPrintf("DoAutomaticDenominating --- connected, sending dsa for %d - denom %d\n", sessionDenom, GetDenominationsByAmount(sessionTotalValue)); return true; diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 2b0d364bb7e2..942848746c93 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -246,21 +246,22 @@ void OverviewPage::updateDarksendProgress(){ } std::ostringstream convert; - //Get average rounds of inputs - double a = ((double)pwalletMain->GetAverageAnonymizedRounds() / (double)nDarksendRounds)*100; - //Get the anon threshold - double max = nAnonymizeDarkcoinAmount; - //If it's more than the wallet amount, limit to that. - if(max > (double)(pwalletMain->GetBalance()/COIN)-1) max = (double)(pwalletMain->GetBalance()/COIN)-1; - //denominated balance / anon threshold -- the percentage that we've completed - double b = ((double)(pwalletMain->GetDenominatedBalance()/COIN) / max); - - double val = a*b; - if(val < 0) val = 0; - if(val > 100) val = 100; - - ui->darksendProgress->setValue(val);//rounds avg * denom progress - convert << "Inputs have an average of " << pwalletMain->GetAverageAnonymizedRounds() << " of " << nDarksendRounds << " rounds (" << a << "/" << b << ")"; + + // Get the anon threshold + int64 max = nAnonymizeDarkcoinAmount*COIN; + + // If it's more than the wallet amount, limit to that. + if(max > balance) max = balance; + + if(max == 0) return; + + // calculate progress + int progress = 100 * pwalletMain->GetNormalizedAnonymizedBalance() / max; + + if(progress > 100) progress = 100; + + ui->darksendProgress->setValue(progress); + convert << "Inputs have an average of " << pwalletMain->GetAverageAnonymizedRounds() << " of " << nDarksendRounds << " rounds"; QString s(convert.str().c_str()); ui->darksendProgress->setToolTip(s); } diff --git a/src/wallet.cpp b/src/wallet.cpp index 798c9fc6ae65..54c42fa3c06b 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1039,6 +1039,33 @@ double CWallet::GetAverageAnonymizedRounds() const return fTotal/fCount; } +int64 CWallet::GetNormalizedAnonymizedBalance() const +{ + int64 nTotal = 0; + + { + LOCK(cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + for (unsigned int i = 0; i < pcoin->vout.size(); i++) { + + COutput out = COutput(pcoin, i, pcoin->GetDepthInMainChain()); + CTxIn vin = CTxIn(out.tx->GetHash(), out.i); + + if(pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]) || !IsDenominated(vin)) continue; + + int rounds = GetInputDarksendRounds(vin); + if(rounds < nDarksendRounds) + nTotal += pcoin->vout[i].nValue * rounds / nDarksendRounds / 2; + else + nTotal += pcoin->vout[i].nValue; + } + } + } + + return nTotal; +} int64 CWallet::GetDenominatedBalance(bool onlyDenom, bool onlyUnconfirmed) const { @@ -1049,21 +1076,25 @@ int64 CWallet::GetDenominatedBalance(bool onlyDenom, bool onlyUnconfirmed) const { const CWalletTx* pcoin = &(*it).second; - bool isDenom = false; - for (unsigned int i = 0; i < pcoin->vout.size(); i++) + for (unsigned int i = 0; i < pcoin->vout.size(); i++){ + + if(pcoin->IsSpent(i) || !IsMine(pcoin->vout[i])) continue; + + bool isDenom = false; BOOST_FOREACH(int64 d, darkSendDenominations) if(pcoin->vout[i].nValue == d) isDenom = true; - if(onlyUnconfirmed){ - if (!pcoin->IsFinal() || !pcoin->IsConfirmed()){ - if(onlyDenom == isDenom){ - nTotal += pcoin->GetAvailableCredit(); + if(onlyUnconfirmed){ + if (!pcoin->IsFinal() || !pcoin->IsConfirmed()){ + if(onlyDenom == isDenom){ + nTotal += pcoin->vout[i].nValue; + } + } + } else if (pcoin->IsConfirmed()) { + if(onlyDenom == isDenom) { + nTotal += pcoin->vout[i].nValue; } - } - } else if (pcoin->IsConfirmed()) { - if(onlyDenom == isDenom) { - nTotal += pcoin->GetAvailableCredit(); } } } diff --git a/src/wallet.h b/src/wallet.h index efeeb3f12778..bfca8e6ea50e 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -204,6 +204,7 @@ class CWallet : public CCryptoKeyStore int64 GetBalance() const; int64 GetAnonymizedBalance() const; double GetAverageAnonymizedRounds() const; + int64 GetNormalizedAnonymizedBalance() const; int64 GetDenominatedBalance(bool onlyDenom=true, bool onlyUnconfirmed=false) const; int64 GetUnconfirmedBalance() const; int64 GetImmatureBalance() const;