diff --git a/src/privatesend/privatesend-client.cpp b/src/privatesend/privatesend-client.cpp index e77c5828b809..0bd2a26cd8c5 100644 --- a/src/privatesend/privatesend-client.cpp +++ b/src/privatesend/privatesend-client.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -1504,8 +1505,15 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, std::vector vecSend; CKeyHolderStorage keyHolderStorageDenom; + CCoinControl coinControl; + // Every input will require at least this much fees in duffs + const CAmount nInputFee = GetMinimumFee(148, coinControl, ::mempool, ::feeEstimator, nullptr /* feeCalc */); + // Every output will require at least this much fees in duffs + const CAmount nOutputFee = GetMinimumFee(34, coinControl, ::mempool, ::feeEstimator, nullptr /* feeCalc */); + CAmount nValueLeft = tallyItem.nAmount; - nValueLeft -= CPrivateSend::GetCollateralAmount(); // leave some room for fees + // Leave some room for fees, assuming we are going to spend all the outpoints + nValueLeft -= tallyItem.vecOutPoints.size() * nInputFee; LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- 0 - %s nValueLeft: %f\n", EncodeDestination(tallyItem.txdest), (float)nValueLeft / COIN); @@ -1514,7 +1522,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, if (fCreateMixingCollaterals) { CScript scriptCollateral = keyHolderStorageDenom.AddKey(GetWallets()[0]); vecSend.push_back((CRecipient){scriptCollateral, CPrivateSend::GetMaxCollateralAmount(), false}); - nValueLeft -= CPrivateSend::GetMaxCollateralAmount(); + nValueLeft -= CPrivateSend::GetMaxCollateralAmount() + nOutputFee; } // ****** Add outputs for denoms ************ / @@ -1546,9 +1554,9 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, int nOutputs = 0; auto needMoreOutputs = [&]() { - bool fRegular = (nValueLeft >= nDenomValue && nBalanceToDenominate >= nDenomValue); + bool fRegular = ((nValueLeft >= nDenomValue + nOutputFee) && nBalanceToDenominate >= nDenomValue); bool fFinal = (fAddFinal - && nValueLeft >= nDenomValue + && nValueLeft >= nDenomValue + nOutputFee && nBalanceToDenominate > 0 && nBalanceToDenominate < nDenomValue); if (fFinal) { @@ -1570,7 +1578,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, // increment outputs and subtract denomination amount nOutputs++; currentDenomIt->second++; - nValueLeft -= nDenomValue; + nValueLeft -= nDenomValue + nOutputFee; nBalanceToDenominate -= nDenomValue; LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- 1 - nDenomValue: %f, totalOutputs: %d, nOutputsTotal: %d, nOutputs: %d, nValueLeft: %f, nBalanceToDenominate: %f\n", @@ -1585,7 +1593,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, for (const auto it : mapDenomCount) { // Check if this specific denom could use another loop, check that there aren't nPrivateSendDenomsGoal of this // denom and that our nValueLeft/nBalanceToDenominate is enough to create one of these denoms, if so, loop again. - if (it.second < privateSendClient.nPrivateSendDenomsGoal && nValueLeft >= it.first && nBalanceToDenominate > 0) { + if (it.second < privateSendClient.nPrivateSendDenomsGoal && (nValueLeft >= it.first + nOutputFee) && nBalanceToDenominate > 0) { finished = false; LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- 1 - NOT finished - nDenomValue: %f, count: %d, nValueLeft: %f, nBalanceToDenominate: %f\n", @@ -1601,7 +1609,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, } // Now that nPrivateSendDenomsGoal worth of each denom have been created or the max number of denoms given the value of the input, do something with the remainder. - if (nValueLeft >= CPrivateSend::GetSmallestDenomination() && nBalanceToDenominate >= CPrivateSend::GetSmallestDenomination() + if ((nValueLeft >= CPrivateSend::GetSmallestDenomination() + nOutputFee) && nBalanceToDenominate >= CPrivateSend::GetSmallestDenomination() && nOutputsTotal < PRIVATESEND_DENOM_OUTPUTS_THRESHOLD) { CAmount nLargestDenomValue = vecStandardDenoms.front(); @@ -1611,7 +1619,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, int nOutputs = 0; // Number of denoms we can create given our denom and the amount of funds we have left - int denomsToCreateValue = nValueLeft / nDenomValue; + int denomsToCreateValue = nValueLeft / (nDenomValue + nOutputFee); int denomsToCreateBal = nBalanceToDenominate / nDenomValue; // Use the smaller value int denomsToCreate = denomsToCreateValue > denomsToCreateBal ? denomsToCreateBal : denomsToCreateValue; @@ -1626,7 +1634,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, // increment outputs and subtract denomination amount nOutputs++; it->second++; - nValueLeft -= nDenomValue; + nValueLeft -= nDenomValue + nOutputFee; nBalanceToDenominate -= nDenomValue; LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- 2 - nDenomValue: %f, totalOutputs: %d, nOutputsTotal: %d, nOutputs: %d, nValueLeft: %f, nBalanceToDenominate: %f\n", @@ -1652,7 +1660,6 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, // if we have anything left over, it will be automatically send back as change - there is no need to send it manually - CCoinControl coinControl; coinControl.fAllowOtherInputs = false; coinControl.fAllowWatchOnly = false; coinControl.nCoinType = CoinType::ONLY_NONDENOMINATED;