diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 7d2f9055ba3e..a4eacd3f0359 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -305,18 +305,14 @@ BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_CPP) endif RES_IMAGES = \ - qt/res/images/arrow_down_normal.png \ - qt/res/images/arrow_down_hover.png \ - qt/res/images/arrow_down_pressed.png \ - qt/res/images/arrow_left_normal.png \ - qt/res/images/arrow_left_hover.png \ - qt/res/images/arrow_left_pressed.png \ - qt/res/images/arrow_right_normal.png \ - qt/res/images/arrow_right_hover.png \ - qt/res/images/arrow_right_pressed.png \ - qt/res/images/arrow_up_normal.png \ - qt/res/images/arrow_up_hover.png \ - qt/res/images/arrow_up_pressed.png \ + qt/res/images/arrow_down_dark.png \ + qt/res/images/arrow_down_light.png \ + qt/res/images/arrow_left_dark.png \ + qt/res/images/arrow_left_light.png \ + qt/res/images/arrow_right_dark.png \ + qt/res/images/arrow_right_light.png \ + qt/res/images/arrow_up_dark.png \ + qt/res/images/arrow_up_light.png \ qt/res/images/arrow_light_down_normal.png \ qt/res/images/arrow_light_down_hover.png \ qt/res/images/arrow_light_left_normal.png \ @@ -325,29 +321,39 @@ RES_IMAGES = \ qt/res/images/arrow_light_right_hover.png \ qt/res/images/arrow_light_up_normal.png \ qt/res/images/arrow_light_up_hover.png \ - qt/res/images/checkbox_normal.png \ - qt/res/images/checkbox_normal_hover.png \ - qt/res/images/checkbox_normal_pressed.png \ - qt/res/images/checkbox_normal_disabled.png \ - qt/res/images/checkbox_checked.png \ - qt/res/images/checkbox_checked_hover.png \ - qt/res/images/checkbox_checked_pressed.png \ - qt/res/images/checkbox_checked_disabled.png \ - qt/res/images/checkbox_partly_checked.png \ - qt/res/images/checkbox_partly_checked_hover.png \ - qt/res/images/checkbox_partly_checked_pressed.png \ - qt/res/images/checkbox_partly_checked_disabled.png \ + qt/res/images/checkbox_normal_dark.png \ + qt/res/images/checkbox_normal_hover_dark.png \ + qt/res/images/checkbox_normal_disabled_dark.png \ + qt/res/images/checkbox_checked_dark.png \ + qt/res/images/checkbox_checked_hover_dark.png \ + qt/res/images/checkbox_checked_disabled_dark.png \ + qt/res/images/checkbox_partly_checked_dark.png \ + qt/res/images/checkbox_partly_checked_hover_dark.png \ + qt/res/images/checkbox_partly_checked_disabled_dark.png \ + qt/res/images/checkbox_normal_light.png \ + qt/res/images/checkbox_normal_hover_light.png \ + qt/res/images/checkbox_normal_disabled_light.png \ + qt/res/images/checkbox_checked_light.png \ + qt/res/images/checkbox_checked_hover_light.png \ + qt/res/images/checkbox_checked_disabled_light.png \ + qt/res/images/checkbox_partly_checked_light.png \ + qt/res/images/checkbox_partly_checked_hover_light.png \ + qt/res/images/checkbox_partly_checked_disabled_light.png \ qt/res/images/dash_logo_horizontal.png \ qt/res/images/dash_logo_toolbar.png \ qt/res/images/dash_logo_toolbar_blue.png \ - qt/res/images/radio_normal.png \ - qt/res/images/radio_normal_hover.png \ - qt/res/images/radio_normal_pressed.png \ - qt/res/images/radio_checked.png \ - qt/res/images/radio_checked_hover.png \ - qt/res/images/radio_checked_pressed.png \ - qt/res/images/radio_normal_disabled.png \ - qt/res/images/radio_checked_disabled.png \ + qt/res/images/radio_normal_dark.png \ + qt/res/images/radio_normal_hover_dark.png \ + qt/res/images/radio_checked_dark.png \ + qt/res/images/radio_checked_hover_dark.png \ + qt/res/images/radio_normal_disabled_dark.png \ + qt/res/images/radio_checked_disabled_dark.png \ + qt/res/images/radio_normal_light.png \ + qt/res/images/radio_normal_hover_light.png \ + qt/res/images/radio_checked_light.png \ + qt/res/images/radio_checked_hover_light.png \ + qt/res/images/radio_normal_disabled_light.png \ + qt/res/images/radio_checked_disabled_light.png \ qt/res/images/splash.png RES_CSS = \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 7cd93c6d87ed..efeb51d4b06d 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -70,7 +70,6 @@ BITCOIN_TESTS =\ test/policyestimator_tests.cpp \ test/pow_tests.cpp \ test/prevector_tests.cpp \ - test/privatesend_tests.cpp \ test/raii_event_tests.cpp \ test/random_tests.cpp \ test/ratecheck_tests.cpp \ @@ -104,6 +103,7 @@ BITCOIN_TESTS =\ if ENABLE_WALLET BITCOIN_TESTS += \ + test/privatesend_tests.cpp \ wallet/test/wallet_test_fixture.cpp \ wallet/test/wallet_test_fixture.h \ wallet/test/accounting_tests.cpp \ diff --git a/src/masternode/masternode-sync.cpp b/src/masternode/masternode-sync.cpp index 80ac79a714ff..d3921640e0fd 100644 --- a/src/masternode/masternode-sync.cpp +++ b/src/masternode/masternode-sync.cpp @@ -16,18 +16,25 @@ class CMasternodeSync; CMasternodeSync masternodeSync; -void CMasternodeSync::Reset() +void CMasternodeSync::Reset(bool fForce, bool fNotifyReset) { - nCurrentAsset = MASTERNODE_SYNC_INITIAL; - nTriedPeerCount = 0; - nTimeAssetSyncStarted = GetTime(); - nTimeLastBumped = GetTime(); - nTimeLastFailure = 0; + // Avoid resetting the sync process if we just "recently" received a new block + if (fForce || (GetTime() - nTimeLastUpdateBlockTip > MASTERNODE_SYNC_RESET_SECONDS)) { + nCurrentAsset = MASTERNODE_SYNC_BLOCKCHAIN; + nTriedPeerCount = 0; + nTimeAssetSyncStarted = GetTime(); + nTimeLastBumped = GetTime(); + nTimeLastUpdateBlockTip = 0; + fReachedBestHeader = false; + if (fNotifyReset) { + uiInterface.NotifyAdditionalDataSyncProgressChanged(-1); + } + } } void CMasternodeSync::BumpAssetLastTime(const std::string& strFuncName) { - if(IsSynced() || IsFailed()) return; + if (IsSynced()) return; nTimeLastBumped = GetTime(); LogPrint(BCLog::MNSYNC, "CMasternodeSync::BumpAssetLastTime -- %s\n", strFuncName); } @@ -36,10 +43,8 @@ std::string CMasternodeSync::GetAssetName() { switch(nCurrentAsset) { - case(MASTERNODE_SYNC_INITIAL): return "MASTERNODE_SYNC_INITIAL"; - case(MASTERNODE_SYNC_WAITING): return "MASTERNODE_SYNC_WAITING"; + case(MASTERNODE_SYNC_BLOCKCHAIN): return "MASTERNODE_SYNC_BLOCKCHAIN"; case(MASTERNODE_SYNC_GOVERNANCE): return "MASTERNODE_SYNC_GOVERNANCE"; - case(MASTERNODE_SYNC_FAILED): return "MASTERNODE_SYNC_FAILED"; case MASTERNODE_SYNC_FINISHED: return "MASTERNODE_SYNC_FINISHED"; default: return "UNKNOWN"; } @@ -49,14 +54,7 @@ void CMasternodeSync::SwitchToNextAsset(CConnman& connman) { switch(nCurrentAsset) { - case(MASTERNODE_SYNC_FAILED): - throw std::runtime_error("Can't switch to next asset from failed, should use Reset() first!"); - break; - case(MASTERNODE_SYNC_INITIAL): - nCurrentAsset = MASTERNODE_SYNC_WAITING; - LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName()); - break; - case(MASTERNODE_SYNC_WAITING): + case(MASTERNODE_SYNC_BLOCKCHAIN): LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %llds\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted); nCurrentAsset = MASTERNODE_SYNC_GOVERNANCE; LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName()); @@ -81,10 +79,8 @@ void CMasternodeSync::SwitchToNextAsset(CConnman& connman) std::string CMasternodeSync::GetSyncStatus() { switch (masternodeSync.nCurrentAsset) { - case MASTERNODE_SYNC_INITIAL: return _("Synchronizing blockchain..."); - case MASTERNODE_SYNC_WAITING: return _("Synchronization pending..."); + case MASTERNODE_SYNC_BLOCKCHAIN: return _("Synchronizing blockchain..."); case MASTERNODE_SYNC_GOVERNANCE: return _("Synchronizing governance objects..."); - case MASTERNODE_SYNC_FAILED: return _("Synchronization failed"); case MASTERNODE_SYNC_FINISHED: return _("Synchronization finished"); default: return ""; } @@ -94,8 +90,8 @@ void CMasternodeSync::ProcessMessage(CNode* pfrom, const std::string& strCommand { if (strCommand == NetMsgType::SYNCSTATUSCOUNT) { //Sync status count - //do not care about stats if sync process finished or failed - if(IsSynced() || IsFailed()) return; + //do not care about stats if sync process finished + if (IsSynced()) return; int nItemID; int nCount; @@ -117,8 +113,7 @@ void CMasternodeSync::ProcessTick(CConnman& connman) static int64_t nTimeLastProcess = GetTime(); if(GetTime() - nTimeLastProcess > 60*60 && !fMasternodeMode) { LogPrintf("CMasternodeSync::ProcessTick -- WARNING: no actions for too long, restarting sync...\n"); - Reset(); - SwitchToNextAsset(connman); + Reset(true); nTimeLastProcess = GetTime(); return; } @@ -130,16 +125,6 @@ void CMasternodeSync::ProcessTick(CConnman& connman) nTimeLastProcess = GetTime(); - // reset sync status in case of any other sync failure - if(IsFailed()) { - if(nTimeLastFailure + (1*60) < GetTime()) { // 1 minute cooldown after failed sync - LogPrintf("CMasternodeSync::ProcessTick -- WARNING: failed to sync, trying again...\n"); - Reset(); - SwitchToNextAsset(connman); - } - return; - } - // gradually request the rest of the votes after sync finished if(IsSynced()) { std::vector vNodesCopy = connman.CopyNodeVector(CConnman::FullyConnectedOnly); @@ -168,7 +153,7 @@ void CMasternodeSync::ProcessTick(CConnman& connman) // QUICK MODE (REGTEST ONLY!) if(Params().NetworkIDString() == CBaseChainParams::REGTEST) { - if (nCurrentAsset == MASTERNODE_SYNC_WAITING) { + if (nCurrentAsset == MASTERNODE_SYNC_BLOCKCHAIN) { connman.PushMessage(pnode, msgMaker.Make(NetMsgType::GETSPORKS)); //get current network sporks SwitchToNextAsset(connman); } else if (nCurrentAsset == MASTERNODE_SYNC_GOVERNANCE) { @@ -205,25 +190,26 @@ void CMasternodeSync::ProcessTick(CConnman& connman) LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nCurrentAsset %d -- requesting sporks from peer=%d\n", nTick, nCurrentAsset, pnode->GetId()); } - // INITIAL TIMEOUT - - if(nCurrentAsset == MASTERNODE_SYNC_WAITING) { + if (nCurrentAsset == MASTERNODE_SYNC_BLOCKCHAIN) { if(pnode->nVersion >= 70216 && !pnode->fInbound && gArgs.GetBoolArg("-syncmempool", DEFAULT_SYNC_MEMPOOL) && !netfulfilledman.HasFulfilledRequest(pnode->addr, "mempool-sync")) { netfulfilledman.AddFulfilledRequest(pnode->addr, "mempool-sync"); connman.PushMessage(pnode, msgMaker.Make(NetMsgType::MEMPOOL)); LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nCurrentAsset %d -- syncing mempool from peer=%d\n", nTick, nCurrentAsset, pnode->GetId()); } - if(GetTime() - nTimeLastBumped > MASTERNODE_SYNC_TIMEOUT_SECONDS) { + int64_t nTimeSyncTimeout = vNodesCopy.size() > 3 ? MASTERNODE_SYNC_TICK_SECONDS : MASTERNODE_SYNC_TIMEOUT_SECONDS; + if (fReachedBestHeader && (GetTime() - nTimeLastBumped > nTimeSyncTimeout)) { // At this point we know that: // a) there are peers (because we are looping on at least one of them); - // b) we waited for at least MASTERNODE_SYNC_TIMEOUT_SECONDS since we reached - // the headers tip the last time (i.e. since we switched from - // MASTERNODE_SYNC_INITIAL to MASTERNODE_SYNC_WAITING and bumped time); + // b) we waited for at least MASTERNODE_SYNC_TICK_SECONDS/MASTERNODE_SYNC_TIMEOUT_SECONDS + // (depending on the number of connected peers) since we reached the headers tip the last + // time (i.e. since fReachedBestHeader has been set to true); // c) there were no blocks (UpdatedBlockTip, NotifyHeaderTip) or headers (AcceptedBlockHeader) - // for at least MASTERNODE_SYNC_TIMEOUT_SECONDS. + // for at least MASTERNODE_SYNC_TICK_SECONDS/MASTERNODE_SYNC_TIMEOUT_SECONDS (depending on + // the number of connected peers). // We must be at the tip already, let's move to the next asset. SwitchToNextAsset(connman); + uiInterface.NotifyAdditionalDataSyncProgressChanged(nSyncProgress); } } @@ -327,7 +313,7 @@ void CMasternodeSync::NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitia { LogPrint(BCLog::MNSYNC, "CMasternodeSync::NotifyHeaderTip -- pindexNew->nHeight: %d fInitialDownload=%d\n", pindexNew->nHeight, fInitialDownload); - if (IsFailed() || IsSynced() || !pindexBestHeader) + if (IsSynced() || !pindexBestHeader) return; if (!IsBlockchainSynced()) { @@ -340,7 +326,9 @@ void CMasternodeSync::UpdatedBlockTip(const CBlockIndex *pindexNew, bool fInitia { LogPrint(BCLog::MNSYNC, "CMasternodeSync::UpdatedBlockTip -- pindexNew->nHeight: %d fInitialDownload=%d\n", pindexNew->nHeight, fInitialDownload); - if (IsFailed() || IsSynced() || !pindexBestHeader) + nTimeLastUpdateBlockTip = GetAdjustedTime(); + + if (IsSynced() || !pindexBestHeader) return; if (!IsBlockchainSynced()) { @@ -351,7 +339,7 @@ void CMasternodeSync::UpdatedBlockTip(const CBlockIndex *pindexNew, bool fInitia if (fInitialDownload) { // switched too early if (IsBlockchainSynced()) { - Reset(); + Reset(true); } // no need to check any further while still in IBD mode @@ -359,28 +347,19 @@ void CMasternodeSync::UpdatedBlockTip(const CBlockIndex *pindexNew, bool fInitia } // Note: since we sync headers first, it should be ok to use this - static bool fReachedBestHeader = false; bool fReachedBestHeaderNew = pindexNew->GetBlockHash() == pindexBestHeader->GetBlockHash(); if (fReachedBestHeader && !fReachedBestHeaderNew) { // Switching from true to false means that we previousely stuck syncing headers for some reason, // probably initial timeout was not enough, // because there is no way we can update tip not having best header - Reset(); - fReachedBestHeader = false; - return; + Reset(true); } fReachedBestHeader = fReachedBestHeaderNew; LogPrint(BCLog::MNSYNC, "CMasternodeSync::UpdatedBlockTip -- pindexNew->nHeight: %d pindexBestHeader->nHeight: %d fInitialDownload=%d fReachedBestHeader=%d\n", pindexNew->nHeight, pindexBestHeader->nHeight, fInitialDownload, fReachedBestHeader); - - if (!IsBlockchainSynced() && fReachedBestHeader) { - // Reached best header while being in initial mode. - // We must be at the tip already, let's move to the next asset. - SwitchToNextAsset(connman); - } } void CMasternodeSync::DoMaintenance(CConnman &connman) diff --git a/src/masternode/masternode-sync.h b/src/masternode/masternode-sync.h index 987dfd0423a8..75512fd1f7cf 100644 --- a/src/masternode/masternode-sync.h +++ b/src/masternode/masternode-sync.h @@ -9,9 +9,7 @@ class CMasternodeSync; -static const int MASTERNODE_SYNC_FAILED = -1; -static const int MASTERNODE_SYNC_INITIAL = 0; // sync just started, was reset recently or still in IDB -static const int MASTERNODE_SYNC_WAITING = 1; // waiting after initial to see if we can get more headers/blocks +static const int MASTERNODE_SYNC_BLOCKCHAIN = 1; static const int MASTERNODE_SYNC_GOVERNANCE = 4; static const int MASTERNODE_SYNC_GOVOBJ = 10; static const int MASTERNODE_SYNC_GOVOBJ_VOTE = 11; @@ -19,6 +17,7 @@ static const int MASTERNODE_SYNC_FINISHED = 999; static const int MASTERNODE_SYNC_TICK_SECONDS = 6; static const int MASTERNODE_SYNC_TIMEOUT_SECONDS = 30; // our blocks are 2.5 minutes so 30 seconds should be fine +static const int MASTERNODE_SYNC_RESET_SECONDS = 600; // Reset fReachedBestHeader in CMasternodeSync::Reset if UpdateBlockTip hasn't been called for this seconds extern CMasternodeSync masternodeSync; @@ -38,17 +37,19 @@ class CMasternodeSync int64_t nTimeAssetSyncStarted; // ... last bumped int64_t nTimeLastBumped; - // ... or failed - int64_t nTimeLastFailure; + + /// Set to true if best header is reached in CMasternodeSync::UpdatedBlockTip + bool fReachedBestHeader{false}; + /// Last time UpdateBlockTip has been called + int64_t nTimeLastUpdateBlockTip{0}; public: - CMasternodeSync() { Reset(); } + CMasternodeSync() { Reset(true, false); } void SendGovernanceSyncRequest(CNode* pnode, CConnman& connman); - bool IsFailed() { return nCurrentAsset == MASTERNODE_SYNC_FAILED; } - bool IsBlockchainSynced() { return nCurrentAsset > MASTERNODE_SYNC_WAITING; } + bool IsBlockchainSynced() { return nCurrentAsset > MASTERNODE_SYNC_BLOCKCHAIN; } bool IsSynced() { return nCurrentAsset == MASTERNODE_SYNC_FINISHED; } int GetAssetID() { return nCurrentAsset; } @@ -58,7 +59,7 @@ class CMasternodeSync std::string GetAssetName(); std::string GetSyncStatus(); - void Reset(); + void Reset(bool fForce = false, bool fNotifyReset = true); void SwitchToNextAsset(CConnman& connman); void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv); diff --git a/src/net.cpp b/src/net.cpp index 8a1c9ae0857a..553b66790e2b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1392,6 +1392,13 @@ void CConnman::NotifyNumConnectionsChanged() LOCK(cs_vNodes); vNodesSize = vNodes.size(); } + + // If we had zero connections before and new connections now or if we just dropped + // to zero connections reset the sync process if its outdated. + if ((vNodesSize > 0 && nPrevNodeCount == 0) || (vNodesSize == 0 && nPrevNodeCount > 0)) { + masternodeSync.Reset(); + } + if(vNodesSize != nPrevNodeCount) { nPrevNodeCount = vNodesSize; if(clientInterface) @@ -2496,7 +2503,7 @@ void CConnman::ThreadOpenMasternodeConnections() didConnect = false; - if (!fNetworkActive) + if (!fNetworkActive || !masternodeSync.IsBlockchainSynced()) continue; std::set connectedNodes; @@ -2886,6 +2893,10 @@ void CConnman::SetNetworkActive(bool active) fNetworkActive = active; + // Always call the Reset() if the network gets enabled/disabled to make sure the sync process + // gets a reset if its outdated.. + masternodeSync.Reset(); + uiInterface.NotifyNetworkActiveChanged(fNetworkActive); } diff --git a/src/privatesend/privatesend-client.cpp b/src/privatesend/privatesend-client.cpp index b9108445a3fb..e6c766bfd1ea 100644 --- a/src/privatesend/privatesend-client.cpp +++ b/src/privatesend/privatesend-client.cpp @@ -859,12 +859,12 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool // there are funds to denominate and denominated balance does not exceed // max amount to mix yet. if (nBalanceAnonimizableNonDenom >= nValueMin + CPrivateSend::GetCollateralAmount() && nBalanceToDenominate > 0) { - CreateDenominated(nBalanceToDenominate, connman); + CreateDenominated(nBalanceToDenominate); } //check if we have the collateral sized inputs if (!GetWallets()[0]->HasCollateralInputs()) { - return !GetWallets()[0]->HasCollateralInputs(false) && MakeCollateralAmounts(connman); + return !GetWallets()[0]->HasCollateralInputs(false) && MakeCollateralAmounts(); } if (nSessionID) { @@ -1321,7 +1321,7 @@ bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds } // Create collaterals by looping through inputs grouped by addresses -bool CPrivateSendClientSession::MakeCollateralAmounts(CConnman& connman) +bool CPrivateSendClientSession::MakeCollateralAmounts() { if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; @@ -1345,13 +1345,13 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(CConnman& connman) // First try to use only non-denominated funds for (const auto& item : vecTally) { - if (!MakeCollateralAmounts(item, false, connman)) continue; + if (!MakeCollateralAmounts(item, false)) continue; return true; } // There should be at least some denominated funds we should be able to break in pieces to continue mixing for (const auto& item : vecTally) { - if (!MakeCollateralAmounts(item, true, connman)) continue; + if (!MakeCollateralAmounts(item, true)) continue; return true; } @@ -1361,7 +1361,7 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(CConnman& connman) } // Split up large inputs or create fee sized inputs -bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& tallyItem, bool fTryDenominated, CConnman& connman) +bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& tallyItem, bool fTryDenominated) { AssertLockHeld(cs_main); AssertLockHeld(mempool.cs); @@ -1369,8 +1369,8 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; - // Skip way too tiny amounts - if (tallyItem.nAmount < CPrivateSend::GetCollateralAmount()) { + // Denominated input is always a single one, so we can check its amount directly and return early + if (!fTryDenominated && tallyItem.vecOutPoints.size() == 1 && CPrivateSend::IsDenominatedAmount(tallyItem.nAmount)) { return false; } @@ -1379,88 +1379,77 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta return false; } - // denominated input is always a single one, so we can check its amount directly and return early - if (!fTryDenominated && tallyItem.vecOutPoints.size() == 1 && CPrivateSend::IsDenominatedAmount(tallyItem.nAmount)) { + CTransactionBuilder txBuilder(GetWallets()[0], tallyItem); + + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- Start %s\n", __func__, txBuilder.ToString()); + + // Skip way too tiny amounts. Smallest we want is minimum collateral amount in a one output tx + if (!txBuilder.CouldAddOutput(CPrivateSend::GetCollateralAmount())) { return false; } - CWalletTx wtx; - CAmount nFeeRet = 0; - int nChangePosRet = -1; - std::string strFail = ""; - std::vector vecSend; + int nCase{0}; // Just for debug logs + if (txBuilder.CouldAddOutputs({CPrivateSend::GetMaxCollateralAmount(), CPrivateSend::GetCollateralAmount()})) { + nCase = 1; + // , see TransactionRecord::decomposeTransaction + // Out1 == CPrivateSend::GetMaxCollateralAmount() + // Out2 >= CPrivateSend::GetCollateralAmount() - // make our collateral address - CReserveKey reservekeyCollateral(GetWallets()[0]); - // make our change address - CReserveKey reservekeyChange(GetWallets()[0]); + txBuilder.AddOutput(CPrivateSend::GetMaxCollateralAmount()); + // Note, here we first add a zero amount output to get the remainder after all fees and then assign it + CTransactionBuilderOutput* out = txBuilder.AddOutput(); + CAmount nAmountLeft = txBuilder.GetAmountLeft(); + // If remainder is denominated add one duff to the fee + out->UpdateAmount(CPrivateSend::IsDenominatedAmount(nAmountLeft) ? nAmountLeft - 1 : nAmountLeft); - CScript scriptCollateral; - CPubKey vchPubKey; - assert(reservekeyCollateral.GetReservedKey(vchPubKey, false)); // should never fail, as we just unlocked - scriptCollateral = GetScriptForDestination(vchPubKey.GetID()); + } else if (txBuilder.CouldAddOutputs({CPrivateSend::GetCollateralAmount(), CPrivateSend::GetCollateralAmount()})) { + nCase = 2; + // , see TransactionRecord::decomposeTransaction + // Out1 CPrivateSend::IsCollateralAmount() + // Out2 CPrivateSend::IsCollateralAmount() - CAmount nCollateralAmount{0}; - if (tallyItem.nAmount > CPrivateSend::GetMaxCollateralAmount() + CPrivateSend::GetCollateralAmount()*2) { - // Change output will be large enough to be valid as a collateral or a source input for another run - nCollateralAmount = CPrivateSend::GetMaxCollateralAmount(); - } else { - // Change output might be too small for another collateral if we try to create the largest collateral - // here, create a slightly smaller one instead - nCollateralAmount = CPrivateSend::GetMaxCollateralAmount() - CPrivateSend::GetCollateralAmount(); - } - vecSend.push_back((CRecipient){scriptCollateral, nCollateralAmount, false}); - - // try to use non-denominated and not mn-like funds first, select them explicitly - CCoinControl coinControl; - coinControl.fAllowOtherInputs = false; - coinControl.fAllowWatchOnly = false; - coinControl.nCoinType = CoinType::ONLY_NONDENOMINATED; - // send change to the same address so that we were able create more denoms out of it later - coinControl.destChange = tallyItem.txdest; - for (const auto& outpoint : tallyItem.vecOutPoints) { - coinControl.Select(outpoint); - } - - bool fSuccess = GetWallets()[0]->CreateTransaction(vecSend, wtx, reservekeyChange, - nFeeRet, nChangePosRet, strFail, coinControl); - if (!fSuccess) { - LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::MakeCollateralAmounts -- ONLY_NONDENOMINATED: %s\n", strFail); - // If we failed then most likely there are not enough funds on this address. - if (fTryDenominated) { - // Try to also use denominated coins (we can't mix denominated without collaterals anyway). - coinControl.nCoinType = CoinType::ALL_COINS; - if (!GetWallets()[0]->CreateTransaction(vecSend, wtx, reservekeyChange, - nFeeRet, nChangePosRet, strFail, coinControl)) { - LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::MakeCollateralAmounts -- ALL_COINS Error: %s\n", strFail); - reservekeyCollateral.ReturnKey(); - return false; - } - } else { - // Nothing else we can do. - reservekeyCollateral.ReturnKey(); - return false; - } + // First add two outputs to get the available value after all fees + CTransactionBuilderOutput* out1 = txBuilder.AddOutput(); + CTransactionBuilderOutput* out2 = txBuilder.AddOutput(); + + // Create two equal outputs from the available value. This adds one duff to the fee if txBuilder.GetAmountLeft() is odd. + CAmount nAmountOutputs = txBuilder.GetAmountLeft() / 2; + + assert(CPrivateSend::IsCollateralAmount(nAmountOutputs)); + + out1->UpdateAmount(nAmountOutputs); + out2->UpdateAmount(nAmountOutputs); + + } else { // still at least possible to add one CPrivateSend::GetCollateralAmount() output + nCase = 3; + // , see TransactionRecord::decomposeTransaction + // Out1 CPrivateSend::IsCollateralAmount() + // Out2 Skipped + CTransactionBuilderOutput* out = txBuilder.AddOutput(); + out->UpdateAmount(txBuilder.GetAmountLeft()); + + assert(CPrivateSend::IsCollateralAmount(out->GetAmount())); } - reservekeyCollateral.KeepKey(); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- Done with case %d: %s\n", __func__, nCase, txBuilder.ToString()); - LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::MakeCollateralAmounts -- txid=%s\n", wtx.GetHash().GetHex()); + assert(txBuilder.IsDust(txBuilder.GetAmountLeft())); - // use the same nCachedLastSuccessBlock as for DS mixing to prevent race - CValidationState state; - if (!GetWallets()[0]->CommitTransaction(wtx, reservekeyChange, &connman, state)) { - LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::MakeCollateralAmounts -- CommitTransaction failed! Reason given: %s\n", state.GetRejectReason()); + std::string strResult; + if (!txBuilder.Commit(strResult)) { + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- Commit failed: %s\n", __func__, strResult); return false; } privateSendClient.UpdatedSuccessBlock(); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- txid: %s\n", __func__, strResult); + return true; } // Create denominations by looping through inputs grouped by addresses -bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, CConnman& connman) +bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate) { if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; @@ -1485,7 +1474,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, bool fCreateMixingCollaterals = !GetWallets()[0]->HasCollateralInputs(); for (const auto& item : vecTally) { - if (!CreateDenominated(nBalanceToDenominate, item, fCreateMixingCollaterals, connman)) continue; + if (!CreateDenominated(nBalanceToDenominate, item, fCreateMixingCollaterals)) continue; return true; } @@ -1494,7 +1483,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, } // Create denominations -bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals, CConnman& connman) +bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals) { AssertLockHeld(cs_main); AssertLockHeld(mempool.cs); @@ -1502,32 +1491,24 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; - 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 */); + // denominated input is always a single one, so we can check its amount directly and return early + if (tallyItem.vecOutPoints.size() == 1 && CPrivateSend::IsDenominatedAmount(tallyItem.nAmount)) { + return false; + } - CAmount nValueLeft = tallyItem.nAmount; - // Leave some room for fees, assuming we are going to spend all the outpoints - nValueLeft -= tallyItem.vecOutPoints.size() * nInputFee; + CTransactionBuilder txBuilder(GetWallets()[0], tallyItem); - LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- 0 - %s nValueLeft: %f\n", EncodeDestination(tallyItem.txdest), (float)nValueLeft / COIN); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- Start %s\n", __func__, txBuilder.ToString()); // ****** Add an output for mixing collaterals ************ / - if (fCreateMixingCollaterals) { - CScript scriptCollateral = keyHolderStorageDenom.AddKey(GetWallets()[0]); - vecSend.push_back((CRecipient){scriptCollateral, CPrivateSend::GetMaxCollateralAmount(), false}); - nValueLeft -= CPrivateSend::GetMaxCollateralAmount() + nOutputFee; + if (fCreateMixingCollaterals && !txBuilder.AddOutput(CPrivateSend::GetMaxCollateralAmount())) { + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- Failed to add collateral output\n", __func__); + return false; } // ****** Add outputs for denoms ************ / - int nOutputsTotal = 0; bool fAddFinal = true; std::vector vecStandardDenoms = CPrivateSend::GetStandardDenominations(); @@ -1545,81 +1526,92 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, // Now, in this system, so long as we don't reach PRIVATESEND_DENOM_OUTPUTS_THRESHOLD outputs the process repeats in // the same transaction, creating up to nPrivateSendDenomsHardCap per denomination in a single transaction. - while (nValueLeft >= CPrivateSend::GetSmallestDenomination() && nOutputsTotal < PRIVATESEND_DENOM_OUTPUTS_THRESHOLD) { - + while (txBuilder.CouldAddOutput(CPrivateSend::GetSmallestDenomination()) && txBuilder.CountOutputs() < PRIVATESEND_DENOM_OUTPUTS_THRESHOLD) { for (auto it = vecStandardDenoms.rbegin(); it != vecStandardDenoms.rend(); ++it) { CAmount nDenomValue = *it; auto currentDenomIt = mapDenomCount.find(nDenomValue); int nOutputs = 0; + const auto& strFunc = __func__; auto needMoreOutputs = [&]() { - bool fRegular = ((nValueLeft >= nDenomValue + nOutputFee) && nBalanceToDenominate >= nDenomValue); - bool fFinal = (fAddFinal - && nValueLeft >= nDenomValue + nOutputFee - && nBalanceToDenominate > 0 - && nBalanceToDenominate < nDenomValue); - if (fFinal) { - fAddFinal = false; // add final denom only once, only the smalest possible one - LogPrint(BCLog::PRIVATESEND, - "CPrivateSendClientSession::CreateDenominated -- 1 - FINAL - nDenomValue: %f, nValueLeft: %f, nBalanceToDenominate: %f\n", - (float) nDenomValue / COIN, (float) nValueLeft / COIN, (float) nBalanceToDenominate / COIN); + if (txBuilder.CouldAddOutput(nDenomValue)) { + if (fAddFinal && nBalanceToDenominate > 0 && nBalanceToDenominate < nDenomValue) { + fAddFinal = false; // add final denom only once, only the smalest possible one + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- 1 - FINAL - nDenomValue: %f, nBalanceToDenominate: %f, nOutputs: %d, %s\n", + strFunc, (float) nDenomValue / COIN, (float) nBalanceToDenominate / COIN, nOutputs, txBuilder.ToString()); + return true; + } else if (nBalanceToDenominate >= nDenomValue) { + return true; + } } - - return fRegular || fFinal; + return false; }; // add each output up to 11 times or until it can't be added again or until we reach nPrivateSendDenomsGoal while (needMoreOutputs() && nOutputs <= 10 && currentDenomIt->second < privateSendClient.nPrivateSendDenomsGoal) { - CScript scriptDenom = keyHolderStorageDenom.AddKey(GetWallets()[0]); - - vecSend.push_back((CRecipient) {scriptDenom, nDenomValue, false}); - - // increment outputs and subtract denomination amount - nOutputs++; - currentDenomIt->second++; - nValueLeft -= nDenomValue + nOutputFee; - nBalanceToDenominate -= nDenomValue; - LogPrint(BCLog::PRIVATESEND, - "CPrivateSendClientSession::CreateDenominated -- 1 - nDenomValue: %f, totalOutputs: %d, nOutputsTotal: %d, nOutputs: %d, nValueLeft: %f, nBalanceToDenominate: %f\n", - (float) nDenomValue / COIN, nOutputsTotal + nOutputs, nOutputsTotal, nOutputs, (float) nValueLeft / COIN, (float) nBalanceToDenominate / COIN); + // Add output and subtract denomination amount + if (txBuilder.AddOutput(nDenomValue)) { + ++nOutputs; + ++currentDenomIt->second; + nBalanceToDenominate -= nDenomValue; + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- 1 - nDenomValue: %f, nBalanceToDenominate: %f, nOutputs: %d, %s\n", + __func__, (float) nDenomValue / COIN, (float) nBalanceToDenominate / COIN, nOutputs, txBuilder.ToString()); + } else { + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- 1 - Error: AddOutput failed for nDenomValue: %f, nBalanceToDenominate: %f, nOutputs: %d, %s\n", + __func__, (float) nDenomValue / COIN, (float) nBalanceToDenominate / COIN, nOutputs, txBuilder.ToString()); + return false; + } + } - nOutputsTotal += nOutputs; - if (nValueLeft == 0 || nBalanceToDenominate <= 0) break; + if (txBuilder.GetAmountLeft() == 0 || nBalanceToDenominate <= 0) break; } bool finished = true; 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 + nOutputFee) && nBalanceToDenominate > 0) { + if (it.second < privateSendClient.nPrivateSendDenomsGoal && txBuilder.CouldAddOutput(it.first) && nBalanceToDenominate > 0) { finished = false; - LogPrint(BCLog::PRIVATESEND, - "CPrivateSendClientSession::CreateDenominated -- 1 - NOT finished - nDenomValue: %f, count: %d, nValueLeft: %f, nBalanceToDenominate: %f\n", - (float) it.first / COIN, it.second, (float) nValueLeft / COIN, (float) nBalanceToDenominate / COIN); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- 1 - NOT finished - nDenomValue: %f, count: %d, nBalanceToDenominate: %f, %s\n", + __func__, (float) it.first / COIN, it.second, (float) nBalanceToDenominate / COIN, txBuilder.ToString()); break; } - LogPrint(BCLog::PRIVATESEND, - "CPrivateSendClientSession::CreateDenominated -- 1 - FINSHED - nDenomValue: %f, count: %d, nValueLeft: %f, nBalanceToDenominate: %f\n", - (float) it.first / COIN, it.second, (float) nValueLeft / COIN, (float) nBalanceToDenominate / COIN); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- 1 - FINSHED - nDenomValue: %f, count: %d, nBalanceToDenominate: %f, %s\n", + __func__, (float) it.first / COIN, it.second, (float) nBalanceToDenominate / COIN, txBuilder.ToString()); } if (finished) break; } // 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() + nOutputFee) && nBalanceToDenominate >= CPrivateSend::GetSmallestDenomination() - && nOutputsTotal < PRIVATESEND_DENOM_OUTPUTS_THRESHOLD) { - + if (txBuilder.CouldAddOutput(CPrivateSend::GetSmallestDenomination()) && nBalanceToDenominate >= CPrivateSend::GetSmallestDenomination() && txBuilder.CountOutputs() < PRIVATESEND_DENOM_OUTPUTS_THRESHOLD) { CAmount nLargestDenomValue = vecStandardDenoms.front(); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- 2 - Process remainder: %s\n", __func__, txBuilder.ToString()); + + auto countPossibleOutputs = [&](CAmount nAmount) -> int { + std::vector vecOutputs; + while (true) { + // Create an potential output + vecOutputs.push_back(nAmount); + if (!txBuilder.CouldAddOutputs(vecOutputs) || txBuilder.CountOutputs() + vecOutputs.size() > PRIVATESEND_DENOM_OUTPUTS_THRESHOLD) { + // If its not possible to add it due to insufficient amount left or total number of outputs exceeds + // PRIVATESEND_DENOM_OUTPUTS_THRESHOLD drop the output again and stop trying. + vecOutputs.pop_back(); + break; + } + } + return static_cast(vecOutputs.size()); + }; + // Go big to small for (auto nDenomValue : vecStandardDenoms) { int nOutputs = 0; // Number of denoms we can create given our denom and the amount of funds we have left - int denomsToCreateValue = nValueLeft / (nDenomValue + nOutputFee); + int denomsToCreateValue = countPossibleOutputs(nDenomValue); // Prefer overshooting the targed balance by larger denoms (hence `+1`) instead of a more // accurate approximation by many smaller denoms. This is ok because when we get here we // should have nPrivateSendDenomsGoal of each smaller denom already. Also, without `+1` @@ -1630,78 +1622,51 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, int denomsToCreateBal = (nBalanceToDenominate / nDenomValue) + 1; // Use the smaller value int denomsToCreate = denomsToCreateValue > denomsToCreateBal ? denomsToCreateBal : denomsToCreateValue; + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- 2 - nBalanceToDenominate: %f, nDenomValue: %f, denomsToCreateValue: %d, denomsToCreateBal: %d\n", + __func__, (float) nBalanceToDenominate / COIN, (float) nDenomValue / COIN, denomsToCreateValue, denomsToCreateBal); auto it = mapDenomCount.find(nDenomValue); for (int i = 0; i < denomsToCreate; i++) { // Never go above the cap unless it's the largest denom if (nDenomValue != nLargestDenomValue && it->second >= privateSendClient.nPrivateSendDenomsHardCap) break; - CScript scriptDenom = keyHolderStorageDenom.AddKey(GetWallets()[0]); - vecSend.push_back((CRecipient) {scriptDenom, nDenomValue, false}); - - // increment outputs and subtract denomination amount - nOutputs++; - it->second++; - nValueLeft -= nDenomValue + nOutputFee; - nBalanceToDenominate -= nDenomValue; - LogPrint(BCLog::PRIVATESEND, - "CPrivateSendClientSession::CreateDenominated -- 2 - nDenomValue: %f, totalOutputs: %d, nOutputsTotal: %d, nOutputs: %d, nValueLeft: %f, nBalanceToDenominate: %f\n", - (float) nDenomValue / COIN, nOutputsTotal + nOutputs, nOutputsTotal, nOutputs, (float) nValueLeft / COIN, (float) nBalanceToDenominate / COIN); - if (nOutputs + nOutputsTotal >= PRIVATESEND_DENOM_OUTPUTS_THRESHOLD) break; + // Increment helpers, add output and subtract denomination amount + if (txBuilder.AddOutput(nDenomValue)) { + nOutputs++; + it->second++; + nBalanceToDenominate -= nDenomValue; + } else { + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- 2 - Error: AddOutput failed at %d/%d, %s\n", __func__, i + 1, denomsToCreate, txBuilder.ToString()); + break; + } + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- 2 - nDenomValue: %f, nBalanceToDenominate: %f, nOutputs: %d, %s\n", + __func__, (float) nDenomValue / COIN, (float) nBalanceToDenominate / COIN, nOutputs, txBuilder.ToString()); + if (txBuilder.CountOutputs() >= PRIVATESEND_DENOM_OUTPUTS_THRESHOLD) break; } - nOutputsTotal += nOutputs; - if (nOutputsTotal >= PRIVATESEND_DENOM_OUTPUTS_THRESHOLD) break; + if (txBuilder.CountOutputs() >= PRIVATESEND_DENOM_OUTPUTS_THRESHOLD) break; } } - LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- 3 - nOutputsTotal: %d, nValueLeft: %f, nBalanceToDenominate: %f\n", - nOutputsTotal, (float)nValueLeft / COIN, (float)nBalanceToDenominate / COIN); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- 3 - nBalanceToDenominate: %f, %s\n", __func__, (float) nBalanceToDenominate / COIN, txBuilder.ToString()); for (const auto it : mapDenomCount) { - LogPrint(BCLog::PRIVATESEND, - "CPrivateSendClientSession::CreateDenominated -- 3 - DONE - nDenomValue: %f, count: %d\n", - (float) it.first / COIN, it.second); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- 3 - DONE - nDenomValue: %f, count: %d\n", __func__, (float) it.first / COIN, it.second); } // No reasons to create mixing collaterals if we can't create denoms to mix - if (nOutputsTotal == 0) return false; - - // if we have anything left over, it will be automatically send back as change - there is no need to send it manually - - coinControl.fAllowOtherInputs = false; - coinControl.fAllowWatchOnly = false; - coinControl.nCoinType = CoinType::ONLY_NONDENOMINATED; - // send change to the same address so that we were able create more denoms out of it later - coinControl.destChange = tallyItem.txdest; - for (const auto& outpoint : tallyItem.vecOutPoints) { - coinControl.Select(outpoint); - } - - CWalletTx wtx; - CAmount nFeeRet = 0; - int nChangePosRet = -1; - std::string strFail = ""; - // make our change address - CReserveKey reservekeyChange(GetWallets()[0]); - - bool fSuccess = GetWallets()[0]->CreateTransaction(vecSend, wtx, reservekeyChange, - nFeeRet, nChangePosRet, strFail, coinControl); - if (!fSuccess) { - LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- Error: %s\n", strFail); - keyHolderStorageDenom.ReturnAll(); + if ((fCreateMixingCollaterals && txBuilder.CountOutputs() == 1) || txBuilder.CountOutputs() == 0) { return false; } - keyHolderStorageDenom.KeepAll(); - - CValidationState state; - if (!GetWallets()[0]->CommitTransaction(wtx, reservekeyChange, &connman, state)) { - LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- CommitTransaction failed! Reason given: %s\n", state.GetRejectReason()); + std::string strResult; + if (!txBuilder.Commit(strResult)) { + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- Commit failed: %s\n", __func__, strResult); return false; } // use the same nCachedLastSuccessBlock as for DS mixing to prevent race privateSendClient.UpdatedSuccessBlock(); - LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- txid=%s\n", wtx.GetHash().GetHex()); + + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- txid: %s\n", __func__, strResult); return true; } diff --git a/src/privatesend/privatesend-client.h b/src/privatesend/privatesend-client.h index 4b1a0a414408..05765f553e49 100644 --- a/src/privatesend/privatesend-client.h +++ b/src/privatesend/privatesend-client.h @@ -111,12 +111,12 @@ class CPrivateSendClientSession : public CPrivateSendBaseSession CKeyHolderStorage keyHolderStorage; // storage for keys used in PrepareDenominate /// Create denominations - bool CreateDenominated(CAmount nBalanceToDenominate, CConnman& connman); - bool CreateDenominated(CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals, CConnman& connman); + bool CreateDenominated(CAmount nBalanceToDenominate); + bool CreateDenominated(CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals); /// Split up large inputs or make fee sized inputs - bool MakeCollateralAmounts(CConnman& connman); - bool MakeCollateralAmounts(const CompactTallyItem& tallyItem, bool fTryDenominated, CConnman& connman); + bool MakeCollateralAmounts(); + bool MakeCollateralAmounts(const CompactTallyItem& tallyItem, bool fTryDenominated); bool JoinExistingQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman); bool StartNewQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman); diff --git a/src/privatesend/privatesend-util.cpp b/src/privatesend/privatesend-util.cpp index 161fd7b4a490..fbfe55ac4d3e 100644 --- a/src/privatesend/privatesend-util.cpp +++ b/src/privatesend/privatesend-util.cpp @@ -2,7 +2,19 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include +#include +#include #include +#include