mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
Coinjoin cs adjustments (#4463)
* Adjust coinjoin-client-options.* by making values atomic, removing CCriticalSection, and adjusting constructor to be default * coinjoin-client.* adjust cs_deqsessions usage * coinjoin add GUARDED_BY notations * coinjoin make some values atomic * coinjoin: move lock to where needed * Ensure values are properly protected * LOCK(cs_vecqueue) as needed * Ensure vecOutputs is properly protected Signed-off-by: pasta <pasta@dashboost.org>
This commit is contained in:
parent
94959c9adc
commit
7508790282
@ -22,28 +22,24 @@ CCoinJoinClientOptions& CCoinJoinClientOptions::Get()
|
|||||||
void CCoinJoinClientOptions::SetEnabled(bool fEnabled)
|
void CCoinJoinClientOptions::SetEnabled(bool fEnabled)
|
||||||
{
|
{
|
||||||
CCoinJoinClientOptions& options = CCoinJoinClientOptions::Get();
|
CCoinJoinClientOptions& options = CCoinJoinClientOptions::Get();
|
||||||
LOCK(options.cs_cj_options);
|
|
||||||
options.fEnableCoinJoin = fEnabled;
|
options.fEnableCoinJoin = fEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCoinJoinClientOptions::SetMultiSessionEnabled(bool fEnabled)
|
void CCoinJoinClientOptions::SetMultiSessionEnabled(bool fEnabled)
|
||||||
{
|
{
|
||||||
CCoinJoinClientOptions& options = CCoinJoinClientOptions::Get();
|
CCoinJoinClientOptions& options = CCoinJoinClientOptions::Get();
|
||||||
LOCK(options.cs_cj_options);
|
|
||||||
options.fCoinJoinMultiSession = fEnabled;
|
options.fCoinJoinMultiSession = fEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCoinJoinClientOptions::SetRounds(int nRounds)
|
void CCoinJoinClientOptions::SetRounds(int nRounds)
|
||||||
{
|
{
|
||||||
CCoinJoinClientOptions& options = CCoinJoinClientOptions::Get();
|
CCoinJoinClientOptions& options = CCoinJoinClientOptions::Get();
|
||||||
LOCK(options.cs_cj_options);
|
|
||||||
options.nCoinJoinRounds = nRounds;
|
options.nCoinJoinRounds = nRounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCoinJoinClientOptions::SetAmount(CAmount amount)
|
void CCoinJoinClientOptions::SetAmount(CAmount amount)
|
||||||
{
|
{
|
||||||
CCoinJoinClientOptions& options = CCoinJoinClientOptions::Get();
|
CCoinJoinClientOptions& options = CCoinJoinClientOptions::Get();
|
||||||
LOCK(options.cs_cj_options);
|
|
||||||
options.nCoinJoinAmount = amount;
|
options.nCoinJoinAmount = amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +47,6 @@ void CCoinJoinClientOptions::Init()
|
|||||||
{
|
{
|
||||||
assert(!CCoinJoinClientOptions::_instance);
|
assert(!CCoinJoinClientOptions::_instance);
|
||||||
static CCoinJoinClientOptions instance;
|
static CCoinJoinClientOptions instance;
|
||||||
LOCK(instance.cs_cj_options);
|
|
||||||
instance.fCoinJoinMultiSession = gArgs.GetBoolArg("-coinjoinmultisession", DEFAULT_COINJOIN_MULTISESSION);
|
instance.fCoinJoinMultiSession = gArgs.GetBoolArg("-coinjoinmultisession", DEFAULT_COINJOIN_MULTISESSION);
|
||||||
instance.nCoinJoinSessions = std::min(std::max((int)gArgs.GetArg("-coinjoinsessions", DEFAULT_COINJOIN_SESSIONS), MIN_COINJOIN_SESSIONS), MAX_COINJOIN_SESSIONS);
|
instance.nCoinJoinSessions = std::min(std::max((int)gArgs.GetArg("-coinjoinsessions", DEFAULT_COINJOIN_SESSIONS), MIN_COINJOIN_SESSIONS), MAX_COINJOIN_SESSIONS);
|
||||||
instance.nCoinJoinRounds = std::min(std::max((int)gArgs.GetArg("-coinjoinrounds", DEFAULT_COINJOIN_ROUNDS), MIN_COINJOIN_ROUNDS), MAX_COINJOIN_ROUNDS);
|
instance.nCoinJoinRounds = std::min(std::max((int)gArgs.GetArg("-coinjoinrounds", DEFAULT_COINJOIN_ROUNDS), MIN_COINJOIN_ROUNDS), MAX_COINJOIN_ROUNDS);
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
#define BITCOIN_COINJOIN_COINJOIN_CLIENT_OPTIONS_H
|
#define BITCOIN_COINJOIN_COINJOIN_CLIENT_OPTIONS_H
|
||||||
|
|
||||||
#include <amount.h>
|
#include <amount.h>
|
||||||
#include <sync.h>
|
#include <atomic>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
class UniValue;
|
class UniValue;
|
||||||
|
|
||||||
@ -72,26 +73,16 @@ private:
|
|||||||
static CCoinJoinClientOptions* _instance;
|
static CCoinJoinClientOptions* _instance;
|
||||||
static std::once_flag onceFlag;
|
static std::once_flag onceFlag;
|
||||||
|
|
||||||
CCriticalSection cs_cj_options;
|
std::atomic<int> nCoinJoinSessions{DEFAULT_COINJOIN_SESSIONS};
|
||||||
int nCoinJoinSessions;
|
std::atomic<int> nCoinJoinRounds{DEFAULT_COINJOIN_ROUNDS};
|
||||||
int nCoinJoinRounds;
|
std::atomic<int> nCoinJoinRandomRounds{COINJOIN_RANDOM_ROUNDS};
|
||||||
int nCoinJoinRandomRounds;
|
std::atomic<int> nCoinJoinAmount{DEFAULT_COINJOIN_AMOUNT};
|
||||||
int nCoinJoinAmount;
|
std::atomic<int> nCoinJoinDenomsGoal{DEFAULT_COINJOIN_DENOMS_GOAL};
|
||||||
int nCoinJoinDenomsGoal;
|
std::atomic<int> nCoinJoinDenomsHardCap{DEFAULT_COINJOIN_DENOMS_HARDCAP};
|
||||||
int nCoinJoinDenomsHardCap;
|
std::atomic<bool> fEnableCoinJoin{false};
|
||||||
bool fEnableCoinJoin;
|
std::atomic<bool> fCoinJoinMultiSession{DEFAULT_COINJOIN_MULTISESSION};
|
||||||
bool fCoinJoinMultiSession;
|
|
||||||
|
|
||||||
CCoinJoinClientOptions() :
|
CCoinJoinClientOptions() = default;
|
||||||
nCoinJoinRounds(DEFAULT_COINJOIN_ROUNDS),
|
|
||||||
nCoinJoinRandomRounds(COINJOIN_RANDOM_ROUNDS),
|
|
||||||
nCoinJoinAmount(DEFAULT_COINJOIN_AMOUNT),
|
|
||||||
nCoinJoinDenomsGoal(DEFAULT_COINJOIN_DENOMS_GOAL),
|
|
||||||
nCoinJoinDenomsHardCap(DEFAULT_COINJOIN_DENOMS_HARDCAP),
|
|
||||||
fEnableCoinJoin(false),
|
|
||||||
fCoinJoinMultiSession(DEFAULT_COINJOIN_MULTISESSION)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CCoinJoinClientOptions(const CCoinJoinClientOptions& other) = delete;
|
CCoinJoinClientOptions(const CCoinJoinClientOptions& other) = delete;
|
||||||
CCoinJoinClientOptions& operator=(const CCoinJoinClientOptions&) = delete;
|
CCoinJoinClientOptions& operator=(const CCoinJoinClientOptions&) = delete;
|
||||||
|
@ -265,9 +265,9 @@ void CCoinJoinClientSession::ResetPool()
|
|||||||
|
|
||||||
void CCoinJoinClientManager::ResetPool()
|
void CCoinJoinClientManager::ResetPool()
|
||||||
{
|
{
|
||||||
LOCK(cs_deqsessions);
|
|
||||||
nCachedLastSuccessBlock = 0;
|
nCachedLastSuccessBlock = 0;
|
||||||
vecMasternodesUsed.clear();
|
vecMasternodesUsed.clear();
|
||||||
|
LOCK(cs_deqsessions);
|
||||||
for (auto& session : deqSessions) {
|
for (auto& session : deqSessions) {
|
||||||
session.ResetPool();
|
session.ResetPool();
|
||||||
}
|
}
|
||||||
@ -346,10 +346,10 @@ std::string CCoinJoinClientSession::GetStatus(bool fWaitForBlock) const
|
|||||||
|
|
||||||
std::string CCoinJoinClientManager::GetStatuses()
|
std::string CCoinJoinClientManager::GetStatuses()
|
||||||
{
|
{
|
||||||
LOCK(cs_deqsessions);
|
|
||||||
std::string strStatus;
|
std::string strStatus;
|
||||||
bool fWaitForBlock = WaitForAnotherBlock();
|
bool fWaitForBlock = WaitForAnotherBlock();
|
||||||
|
|
||||||
|
LOCK(cs_deqsessions);
|
||||||
for (const auto& session : deqSessions) {
|
for (const auto& session : deqSessions) {
|
||||||
strStatus += session.GetStatus(fWaitForBlock) + "; ";
|
strStatus += session.GetStatus(fWaitForBlock) + "; ";
|
||||||
}
|
}
|
||||||
@ -358,9 +358,9 @@ std::string CCoinJoinClientManager::GetStatuses()
|
|||||||
|
|
||||||
std::string CCoinJoinClientManager::GetSessionDenoms()
|
std::string CCoinJoinClientManager::GetSessionDenoms()
|
||||||
{
|
{
|
||||||
LOCK(cs_deqsessions);
|
|
||||||
std::string strSessionDenoms;
|
std::string strSessionDenoms;
|
||||||
|
|
||||||
|
LOCK(cs_deqsessions);
|
||||||
for (const auto& session : deqSessions) {
|
for (const auto& session : deqSessions) {
|
||||||
strSessionDenoms += CCoinJoin::DenominationToString(session.nSessionDenom) + "; ";
|
strSessionDenoms += CCoinJoin::DenominationToString(session.nSessionDenom) + "; ";
|
||||||
}
|
}
|
||||||
@ -490,6 +490,7 @@ bool CCoinJoinClientSession::SendDenominate(const std::vector<std::pair<CTxDSIn,
|
|||||||
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::SendDenominate -- Submitting partial tx %s", tx.ToString()); /* Continued */
|
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::SendDenominate -- Submitting partial tx %s", tx.ToString()); /* Continued */
|
||||||
|
|
||||||
// store our entry for later use
|
// store our entry for later use
|
||||||
|
LOCK(cs_coinjoin);
|
||||||
vecEntries.emplace_back(vecTxDSInTmp, vecTxOutTmp, txMyCollateral);
|
vecEntries.emplace_back(vecTxDSInTmp, vecTxOutTmp, txMyCollateral);
|
||||||
RelayIn(vecEntries.back(), connman);
|
RelayIn(vecEntries.back(), connman);
|
||||||
nTimeLastSuccessfulStep = GetTime();
|
nTimeLastSuccessfulStep = GetTime();
|
||||||
@ -557,6 +558,8 @@ bool CCoinJoinClientSession::SignFinalTransaction(const CTransaction& finalTrans
|
|||||||
if (fMasternodeMode || pnode == nullptr) return false;
|
if (fMasternodeMode || pnode == nullptr) return false;
|
||||||
if (!mixingMasternode) return false;
|
if (!mixingMasternode) return false;
|
||||||
|
|
||||||
|
LOCK(cs_coinjoin);
|
||||||
|
|
||||||
finalMutableTransaction = CMutableTransaction{finalTransactionNew};
|
finalMutableTransaction = CMutableTransaction{finalTransactionNew};
|
||||||
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- finalMutableTransaction=%s", __func__, finalMutableTransaction.ToString()); /* Continued */
|
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- finalMutableTransaction=%s", __func__, finalMutableTransaction.ToString()); /* Continued */
|
||||||
|
|
||||||
@ -588,11 +591,11 @@ bool CCoinJoinClientSession::SignFinalTransaction(const CTransaction& finalTrans
|
|||||||
|
|
||||||
std::vector<CTxIn> sigs;
|
std::vector<CTxIn> sigs;
|
||||||
|
|
||||||
for (const auto& entry : vecEntries) {
|
for (const auto &entry: vecEntries) {
|
||||||
// Check that the final transaction has all our outputs
|
// Check that the final transaction has all our outputs
|
||||||
for (const auto& txout : entry.vecTxOut) {
|
for (const auto &txout: entry.vecTxOut) {
|
||||||
bool fFound = false;
|
bool fFound = false;
|
||||||
for (const auto& txoutFinal : finalMutableTransaction.vout) {
|
for (const auto &txoutFinal: finalMutableTransaction.vout) {
|
||||||
if (txoutFinal == txout) {
|
if (txoutFinal == txout) {
|
||||||
fFound = true;
|
fFound = true;
|
||||||
break;
|
break;
|
||||||
@ -641,7 +644,7 @@ bool CCoinJoinClientSession::SignFinalTransaction(const CTransaction& finalTrans
|
|||||||
|
|
||||||
sigs.push_back(finalMutableTransaction.vin[nMyInputIndex]);
|
sigs.push_back(finalMutableTransaction.vin[nMyInputIndex]);
|
||||||
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- nMyInputIndex: %d, sigs.size(): %d, scriptSig=%s\n",
|
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- nMyInputIndex: %d, sigs.size(): %d, scriptSig=%s\n",
|
||||||
__func__, nMyInputIndex, (int)sigs.size(), ScriptToAsmStr(finalMutableTransaction.vin[nMyInputIndex].scriptSig));
|
__func__, nMyInputIndex, (int) sigs.size(),ScriptToAsmStr(finalMutableTransaction.vin[nMyInputIndex].scriptSig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -973,8 +976,8 @@ bool CCoinJoinClientManager::DoAutomaticDenominating(CConnman& connman, bool fDr
|
|||||||
LogPrint(BCLog::COINJOIN, " vecMasternodesUsed: new size: %d, threshold: %d\n", (int)vecMasternodesUsed.size(), nThreshold_high);
|
LogPrint(BCLog::COINJOIN, " vecMasternodesUsed: new size: %d, threshold: %d\n", (int)vecMasternodesUsed.size(), nThreshold_high);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK(cs_deqsessions);
|
|
||||||
bool fResult = true;
|
bool fResult = true;
|
||||||
|
LOCK(cs_deqsessions);
|
||||||
if ((int)deqSessions.size() < CCoinJoinClientOptions::GetSessions()) {
|
if ((int)deqSessions.size() < CCoinJoinClientOptions::GetSessions()) {
|
||||||
deqSessions.emplace_back(mixingWallet);
|
deqSessions.emplace_back(mixingWallet);
|
||||||
}
|
}
|
||||||
@ -1865,11 +1868,11 @@ void CCoinJoinClientSession::GetJsonInfo(UniValue& obj) const
|
|||||||
|
|
||||||
void CCoinJoinClientManager::GetJsonInfo(UniValue& obj) const
|
void CCoinJoinClientManager::GetJsonInfo(UniValue& obj) const
|
||||||
{
|
{
|
||||||
LOCK(cs_deqsessions);
|
|
||||||
assert(obj.isObject());
|
assert(obj.isObject());
|
||||||
obj.pushKV("running", IsMixing());
|
obj.pushKV("running", IsMixing());
|
||||||
|
|
||||||
UniValue arrSessions(UniValue::VARR);
|
UniValue arrSessions(UniValue::VARR);
|
||||||
|
LOCK(cs_deqsessions);
|
||||||
for (const auto& session : deqSessions) {
|
for (const auto& session : deqSessions) {
|
||||||
if (session.GetState() != POOL_STATE_IDLE) {
|
if (session.GetState() != POOL_STATE_IDLE) {
|
||||||
UniValue objSession(UniValue::VOBJ);
|
UniValue objSession(UniValue::VOBJ);
|
||||||
|
@ -174,9 +174,9 @@ private:
|
|||||||
// Keep track of the used Masternodes
|
// Keep track of the used Masternodes
|
||||||
std::vector<COutPoint> vecMasternodesUsed;
|
std::vector<COutPoint> vecMasternodesUsed;
|
||||||
|
|
||||||
// TODO: or map<denom, CCoinJoinClientSession> ??
|
|
||||||
std::deque<CCoinJoinClientSession> deqSessions;
|
|
||||||
mutable CCriticalSection cs_deqsessions;
|
mutable CCriticalSection cs_deqsessions;
|
||||||
|
// TODO: or map<denom, CCoinJoinClientSession> ??
|
||||||
|
std::deque<CCoinJoinClientSession> deqSessions GUARDED_BY(cs_deqsessions);
|
||||||
|
|
||||||
bool fMixing{false};
|
bool fMixing{false};
|
||||||
|
|
||||||
|
@ -302,6 +302,8 @@ void CCoinJoinServer::CreateFinalTransaction(CConnman& connman)
|
|||||||
{
|
{
|
||||||
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CreateFinalTransaction -- FINALIZE TRANSACTIONS\n");
|
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CreateFinalTransaction -- FINALIZE TRANSACTIONS\n");
|
||||||
|
|
||||||
|
LOCK(cs_coinjoin);
|
||||||
|
|
||||||
CMutableTransaction txNew;
|
CMutableTransaction txNew;
|
||||||
|
|
||||||
// make our new transaction
|
// make our new transaction
|
||||||
@ -329,7 +331,7 @@ void CCoinJoinServer::CommitFinalTransaction(CConnman& connman)
|
|||||||
{
|
{
|
||||||
if (!fMasternodeMode) return; // check and relay final tx only on masternode
|
if (!fMasternodeMode) return; // check and relay final tx only on masternode
|
||||||
|
|
||||||
CTransactionRef finalTransaction = MakeTransactionRef(finalMutableTransaction);
|
CTransactionRef finalTransaction = WITH_LOCK(cs_coinjoin, return MakeTransactionRef(finalMutableTransaction));
|
||||||
uint256 hashTx = finalTransaction->GetHash();
|
uint256 hashTx = finalTransaction->GetHash();
|
||||||
|
|
||||||
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CommitFinalTransaction -- finalTransaction=%s", finalTransaction->ToString()); /* Continued */
|
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CommitFinalTransaction -- finalTransaction=%s", finalTransaction->ToString()); /* Continued */
|
||||||
@ -395,6 +397,7 @@ void CCoinJoinServer::ChargeFees(CConnman& connman) const
|
|||||||
std::vector<CTransactionRef> vecOffendersCollaterals;
|
std::vector<CTransactionRef> vecOffendersCollaterals;
|
||||||
|
|
||||||
if (nState == POOL_STATE_ACCEPTING_ENTRIES) {
|
if (nState == POOL_STATE_ACCEPTING_ENTRIES) {
|
||||||
|
LOCK(cs_coinjoin);
|
||||||
for (const auto& txCollateral : vecSessionCollaterals) {
|
for (const auto& txCollateral : vecSessionCollaterals) {
|
||||||
bool fFound = false;
|
bool fFound = false;
|
||||||
for (const auto& entry : vecEntries) {
|
for (const auto& entry : vecEntries) {
|
||||||
@ -414,6 +417,7 @@ void CCoinJoinServer::ChargeFees(CConnman& connman) const
|
|||||||
|
|
||||||
if (nState == POOL_STATE_SIGNING) {
|
if (nState == POOL_STATE_SIGNING) {
|
||||||
// who didn't sign?
|
// who didn't sign?
|
||||||
|
LOCK(cs_coinjoin);
|
||||||
for (const auto& entry : vecEntries) {
|
for (const auto& entry : vecEntries) {
|
||||||
for (const auto& txdsin : entry.vecTxDSIn) {
|
for (const auto& txdsin : entry.vecTxDSIn) {
|
||||||
if (!txdsin.fHasSig) {
|
if (!txdsin.fHasSig) {
|
||||||
@ -538,21 +542,23 @@ bool CCoinJoinServer::IsInputScriptSigValid(const CTxIn& txin) const
|
|||||||
int nTxInIndex = -1;
|
int nTxInIndex = -1;
|
||||||
CScript sigPubKey = CScript();
|
CScript sigPubKey = CScript();
|
||||||
|
|
||||||
for (const auto& entry : vecEntries) {
|
{
|
||||||
for (const auto& txout : entry.vecTxOut) {
|
LOCK(cs_coinjoin);
|
||||||
txNew.vout.push_back(txout);
|
for (const auto &entry: vecEntries) {
|
||||||
}
|
for (const auto &txout: entry.vecTxOut) {
|
||||||
for (const auto& txdsin : entry.vecTxDSIn) {
|
txNew.vout.push_back(txout);
|
||||||
txNew.vin.push_back(txdsin);
|
}
|
||||||
|
for (const auto &txdsin: entry.vecTxDSIn) {
|
||||||
if (txdsin.prevout == txin.prevout) {
|
txNew.vin.push_back(txdsin);
|
||||||
nTxInIndex = i;
|
|
||||||
sigPubKey = txdsin.prevPubKey;
|
if (txdsin.prevout == txin.prevout) {
|
||||||
|
nTxInIndex = i;
|
||||||
|
sigPubKey = txdsin.prevPubKey;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nTxInIndex >= 0) { //might have to do this one input at a time?
|
if (nTxInIndex >= 0) { //might have to do this one input at a time?
|
||||||
txNew.vin[nTxInIndex].scriptSig = txin.scriptSig;
|
txNew.vin[nTxInIndex].scriptSig = txin.scriptSig;
|
||||||
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::IsInputScriptSigValid -- verifying scriptSig %s\n", ScriptToAsmStr(txin.scriptSig).substr(0, 24));
|
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::IsInputScriptSigValid -- verifying scriptSig %s\n", ScriptToAsmStr(txin.scriptSig).substr(0, 24));
|
||||||
@ -599,7 +605,7 @@ bool CCoinJoinServer::AddEntry(CConnman& connman, const CCoinJoinEntry& entry, P
|
|||||||
std::vector<CTxIn> vin;
|
std::vector<CTxIn> vin;
|
||||||
for (const auto& txin : entry.vecTxDSIn) {
|
for (const auto& txin : entry.vecTxDSIn) {
|
||||||
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- txin=%s\n", __func__, txin.ToString());
|
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- txin=%s\n", __func__, txin.ToString());
|
||||||
|
LOCK(cs_coinjoin);
|
||||||
for (const auto& inner_entry : vecEntries) {
|
for (const auto& inner_entry : vecEntries) {
|
||||||
for (const auto& txdsin : inner_entry.vecTxDSIn) {
|
for (const auto& txdsin : inner_entry.vecTxDSIn) {
|
||||||
if (txdsin.prevout == txin.prevout) {
|
if (txdsin.prevout == txin.prevout) {
|
||||||
@ -624,7 +630,7 @@ bool CCoinJoinServer::AddEntry(CConnman& connman, const CCoinJoinEntry& entry, P
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vecEntries.push_back(entry);
|
WITH_LOCK(cs_coinjoin, vecEntries.push_back(entry));
|
||||||
|
|
||||||
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- adding entry %d of %d required\n", __func__, GetEntriesCount(), CCoinJoin::GetMaxPoolParticipants());
|
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- adding entry %d of %d required\n", __func__, GetEntriesCount(), CCoinJoin::GetMaxPoolParticipants());
|
||||||
nMessageIDRet = MSG_ENTRIES_ADDED;
|
nMessageIDRet = MSG_ENTRIES_ADDED;
|
||||||
@ -636,6 +642,7 @@ bool CCoinJoinServer::AddScriptSig(const CTxIn& txinNew)
|
|||||||
{
|
{
|
||||||
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::AddScriptSig -- scriptSig=%s\n", ScriptToAsmStr(txinNew.scriptSig).substr(0, 24));
|
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::AddScriptSig -- scriptSig=%s\n", ScriptToAsmStr(txinNew.scriptSig).substr(0, 24));
|
||||||
|
|
||||||
|
LOCK(cs_coinjoin);
|
||||||
for (const auto& entry : vecEntries) {
|
for (const auto& entry : vecEntries) {
|
||||||
for (const auto& txdsin : entry.vecTxDSIn) {
|
for (const auto& txdsin : entry.vecTxDSIn) {
|
||||||
if (txdsin.scriptSig == txinNew.scriptSig) {
|
if (txdsin.scriptSig == txinNew.scriptSig) {
|
||||||
@ -672,6 +679,7 @@ bool CCoinJoinServer::AddScriptSig(const CTxIn& txinNew)
|
|||||||
// Check to make sure everything is signed
|
// Check to make sure everything is signed
|
||||||
bool CCoinJoinServer::IsSignaturesComplete() const
|
bool CCoinJoinServer::IsSignaturesComplete() const
|
||||||
{
|
{
|
||||||
|
LOCK(cs_coinjoin);
|
||||||
for (const auto& entry : vecEntries) {
|
for (const auto& entry : vecEntries) {
|
||||||
for (const auto& txdsin : entry.vecTxDSIn) {
|
for (const auto& txdsin : entry.vecTxDSIn) {
|
||||||
if (!txdsin.fHasSig) return false;
|
if (!txdsin.fHasSig) return false;
|
||||||
@ -730,6 +738,7 @@ bool CCoinJoinServer::CreateNewSession(const CCoinJoinAccept& dsa, PoolMessage&
|
|||||||
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CreateNewSession -- signing and relaying new queue: %s\n", dsq.ToString());
|
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CreateNewSession -- signing and relaying new queue: %s\n", dsq.ToString());
|
||||||
dsq.Sign();
|
dsq.Sign();
|
||||||
dsq.Relay(connman);
|
dsq.Relay(connman);
|
||||||
|
LOCK(cs_vecqueue);
|
||||||
vecCoinJoinQueue.push_back(dsq);
|
vecCoinJoinQueue.push_back(dsq);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -796,10 +805,11 @@ void CCoinJoinServer::RelayFinalTransaction(const CTransaction& txFinal, CConnma
|
|||||||
__func__, nSessionID, nSessionDenom, CCoinJoin::DenominationToString(nSessionDenom));
|
__func__, nSessionID, nSessionDenom, CCoinJoin::DenominationToString(nSessionDenom));
|
||||||
|
|
||||||
// final mixing tx with empty signatures should be relayed to mixing participants only
|
// final mixing tx with empty signatures should be relayed to mixing participants only
|
||||||
|
LOCK(cs_coinjoin);
|
||||||
for (const auto& entry : vecEntries) {
|
for (const auto& entry : vecEntries) {
|
||||||
bool fOk = connman.ForNode(entry.addr, [&txFinal, &connman, this](CNode* pnode) {
|
bool fOk = connman.ForNode(entry.addr, [&txFinal, &connman, this](CNode* pnode) {
|
||||||
CNetMsgMaker msgMaker(pnode->GetSendVersion());
|
CNetMsgMaker msgMaker(pnode->GetSendVersion());
|
||||||
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSFINALTX, nSessionID, txFinal));
|
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSFINALTX, nSessionID.load(), txFinal));
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
if (!fOk) {
|
if (!fOk) {
|
||||||
@ -821,6 +831,7 @@ void CCoinJoinServer::RelayStatus(PoolStatusUpdate nStatusUpdate, CConnman& conn
|
|||||||
{
|
{
|
||||||
unsigned int nDisconnected{};
|
unsigned int nDisconnected{};
|
||||||
// status updates should be relayed to mixing participants only
|
// status updates should be relayed to mixing participants only
|
||||||
|
LOCK(cs_coinjoin);
|
||||||
for (const auto& entry : vecEntries) {
|
for (const auto& entry : vecEntries) {
|
||||||
// make sure everyone is still connected
|
// make sure everyone is still connected
|
||||||
bool fOk = connman.ForNode(entry.addr, [&nStatusUpdate, &nMessageID, &connman, this](CNode* pnode) {
|
bool fOk = connman.ForNode(entry.addr, [&nStatusUpdate, &nMessageID, &connman, this](CNode* pnode) {
|
||||||
@ -859,10 +870,11 @@ void CCoinJoinServer::RelayCompletedTransaction(PoolMessage nMessageID, CConnman
|
|||||||
__func__, nSessionID, nSessionDenom, CCoinJoin::DenominationToString(nSessionDenom));
|
__func__, nSessionID, nSessionDenom, CCoinJoin::DenominationToString(nSessionDenom));
|
||||||
|
|
||||||
// final mixing tx with empty signatures should be relayed to mixing participants only
|
// final mixing tx with empty signatures should be relayed to mixing participants only
|
||||||
|
LOCK(cs_coinjoin);
|
||||||
for (const auto& entry : vecEntries) {
|
for (const auto& entry : vecEntries) {
|
||||||
bool fOk = connman.ForNode(entry.addr, [&nMessageID, &connman, this](CNode* pnode) {
|
bool fOk = connman.ForNode(entry.addr, [&nMessageID, &connman, this](CNode* pnode) {
|
||||||
CNetMsgMaker msgMaker(pnode->GetSendVersion());
|
CNetMsgMaker msgMaker(pnode->GetSendVersion());
|
||||||
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSCOMPLETE, nSessionID, nMessageID));
|
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSCOMPLETE, nSessionID.load(), nMessageID));
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
if (!fOk) {
|
if (!fOk) {
|
||||||
|
@ -98,7 +98,6 @@ CTransactionBuilderOutput::CTransactionBuilderOutput(CTransactionBuilder* pTxBui
|
|||||||
|
|
||||||
bool CTransactionBuilderOutput::UpdateAmount(const CAmount nNewAmount)
|
bool CTransactionBuilderOutput::UpdateAmount(const CAmount nNewAmount)
|
||||||
{
|
{
|
||||||
LOCK(pTxBuilder->cs_outputs);
|
|
||||||
if (nNewAmount <= 0 || nNewAmount - nAmount > pTxBuilder->GetAmountLeft()) {
|
if (nNewAmount <= 0 || nNewAmount - nAmount > pTxBuilder->GetAmountLeft()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -200,8 +199,8 @@ bool CTransactionBuilder::CouldAddOutputs(const std::vector<CAmount>& vecOutputA
|
|||||||
|
|
||||||
CTransactionBuilderOutput* CTransactionBuilder::AddOutput(CAmount nAmountOutput)
|
CTransactionBuilderOutput* CTransactionBuilder::AddOutput(CAmount nAmountOutput)
|
||||||
{
|
{
|
||||||
LOCK(cs_outputs);
|
|
||||||
if (CouldAddOutput(nAmountOutput)) {
|
if (CouldAddOutput(nAmountOutput)) {
|
||||||
|
LOCK(cs_outputs);
|
||||||
vecOutputs.push_back(std::make_unique<CTransactionBuilderOutput>(this, pwallet, nAmountOutput));
|
vecOutputs.push_back(std::make_unique<CTransactionBuilderOutput>(this, pwallet, nAmountOutput));
|
||||||
return vecOutputs.back().get();
|
return vecOutputs.back().get();
|
||||||
}
|
}
|
||||||
@ -210,6 +209,7 @@ CTransactionBuilderOutput* CTransactionBuilder::AddOutput(CAmount nAmountOutput)
|
|||||||
|
|
||||||
unsigned int CTransactionBuilder::GetBytesTotal() const
|
unsigned int CTransactionBuilder::GetBytesTotal() const
|
||||||
{
|
{
|
||||||
|
LOCK(cs_outputs);
|
||||||
// Adding other outputs can change the serialized size of the vout size hence + GetSizeOfCompactSizeDiff()
|
// Adding other outputs can change the serialized size of the vout size hence + GetSizeOfCompactSizeDiff()
|
||||||
return nBytesBase + vecOutputs.size() * nBytesOutput + ::GetSizeOfCompactSizeDiff(0, vecOutputs.size());
|
return nBytesBase + vecOutputs.size() * nBytesOutput + ::GetSizeOfCompactSizeDiff(0, vecOutputs.size());
|
||||||
}
|
}
|
||||||
@ -222,6 +222,7 @@ CAmount CTransactionBuilder::GetAmountLeft(const CAmount nAmountInitial, const C
|
|||||||
CAmount CTransactionBuilder::GetAmountUsed() const
|
CAmount CTransactionBuilder::GetAmountUsed() const
|
||||||
{
|
{
|
||||||
CAmount nAmountUsed{0};
|
CAmount nAmountUsed{0};
|
||||||
|
LOCK(cs_outputs);
|
||||||
for (const auto& out : vecOutputs) {
|
for (const auto& out : vecOutputs) {
|
||||||
nAmountUsed += out->GetAmount();
|
nAmountUsed += out->GetAmount();
|
||||||
}
|
}
|
||||||
@ -243,7 +244,7 @@ CAmount CTransactionBuilder::GetFee(unsigned int nBytes) const
|
|||||||
|
|
||||||
int CTransactionBuilder::GetSizeOfCompactSizeDiff(size_t nAdd) const
|
int CTransactionBuilder::GetSizeOfCompactSizeDiff(size_t nAdd) const
|
||||||
{
|
{
|
||||||
size_t nSize = vecOutputs.size();
|
size_t nSize = WITH_LOCK(cs_outputs, return vecOutputs.size());
|
||||||
unsigned int ret = ::GetSizeOfCompactSizeDiff(nSize, nSize + nAdd);
|
unsigned int ret = ::GetSizeOfCompactSizeDiff(nSize, nSize + nAdd);
|
||||||
assert(ret <= INT_MAX);
|
assert(ret <= INT_MAX);
|
||||||
return (int)ret;
|
return (int)ret;
|
||||||
|
@ -28,8 +28,8 @@ public:
|
|||||||
class CKeyHolderStorage
|
class CKeyHolderStorage
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<CKeyHolder> > storage;
|
|
||||||
mutable CCriticalSection cs_storage;
|
mutable CCriticalSection cs_storage;
|
||||||
|
std::vector<std::unique_ptr<CKeyHolder> > storage GUARDED_BY(cs_storage);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CScript AddKey(CWallet* pwalletIn);
|
CScript AddKey(CWallet* pwalletIn);
|
||||||
@ -94,7 +94,7 @@ class CTransactionBuilder
|
|||||||
/// Protect vecOutputs
|
/// Protect vecOutputs
|
||||||
mutable CCriticalSection cs_outputs;
|
mutable CCriticalSection cs_outputs;
|
||||||
/// Contains all outputs already added to the transaction
|
/// Contains all outputs already added to the transaction
|
||||||
std::vector<std::unique_ptr<CTransactionBuilderOutput>> vecOutputs;
|
std::vector<std::unique_ptr<CTransactionBuilderOutput>> vecOutputs GUARDED_BY(cs_outputs);
|
||||||
/// Needed by CTransactionBuilderOutput::UpdateAmount to lock cs_outputs
|
/// Needed by CTransactionBuilderOutput::UpdateAmount to lock cs_outputs
|
||||||
friend class CTransactionBuilderOutput;
|
friend class CTransactionBuilderOutput;
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ public:
|
|||||||
/// Check if an amounts should be considered as dust
|
/// Check if an amounts should be considered as dust
|
||||||
bool IsDust(CAmount nAmount) const;
|
bool IsDust(CAmount nAmount) const;
|
||||||
/// Get the total number of added outputs
|
/// Get the total number of added outputs
|
||||||
int CountOutputs() const { return vecOutputs.size(); }
|
int CountOutputs() const { LOCK(cs_outputs); return vecOutputs.size(); }
|
||||||
/// Create and Commit the transaction to the wallet
|
/// Create and Commit the transaction to the wallet
|
||||||
bool Commit(std::string& strResult);
|
bool Commit(std::string& strResult);
|
||||||
/// Convert to a string
|
/// Convert to a string
|
||||||
|
@ -303,8 +303,8 @@ bool CCoinJoinBaseSession::IsValidInOuts(const std::vector<CTxIn>& vin, const st
|
|||||||
|
|
||||||
// Definitions for static data members
|
// Definitions for static data members
|
||||||
std::vector<CAmount> CCoinJoin::vecStandardDenominations;
|
std::vector<CAmount> CCoinJoin::vecStandardDenominations;
|
||||||
std::map<uint256, CCoinJoinBroadcastTx> CCoinJoin::mapDSTX;
|
|
||||||
CCriticalSection CCoinJoin::cs_mapdstx;
|
CCriticalSection CCoinJoin::cs_mapdstx;
|
||||||
|
std::map<uint256, CCoinJoinBroadcastTx> CCoinJoin::mapDSTX GUARDED_BY(CCoinJoin::cs_mapdstx);
|
||||||
|
|
||||||
void CCoinJoin::InitStandardDenominations()
|
void CCoinJoin::InitStandardDenominations()
|
||||||
{
|
{
|
||||||
|
@ -337,14 +337,14 @@ class CCoinJoinBaseSession
|
|||||||
protected:
|
protected:
|
||||||
mutable CCriticalSection cs_coinjoin;
|
mutable CCriticalSection cs_coinjoin;
|
||||||
|
|
||||||
std::vector<CCoinJoinEntry> vecEntries; // Masternode/clients entries
|
std::vector<CCoinJoinEntry> vecEntries GUARDED_BY(cs_coinjoin); // Masternode/clients entries
|
||||||
|
|
||||||
PoolState nState; // should be one of the POOL_STATE_XXX values
|
std::atomic<PoolState> nState; // should be one of the POOL_STATE_XXX values
|
||||||
int64_t nTimeLastSuccessfulStep; // the time when last successful mixing step was performed
|
std::atomic<int64_t> nTimeLastSuccessfulStep; // the time when last successful mixing step was performed
|
||||||
|
|
||||||
int nSessionID; // 0 if no mixing session is active
|
std::atomic<int> nSessionID; // 0 if no mixing session is active
|
||||||
|
|
||||||
CMutableTransaction finalMutableTransaction; // the finalized transaction ready for signing
|
CMutableTransaction finalMutableTransaction GUARDED_BY(cs_coinjoin); // the finalized transaction ready for signing
|
||||||
|
|
||||||
void SetNull();
|
void SetNull();
|
||||||
|
|
||||||
@ -366,7 +366,7 @@ public:
|
|||||||
int GetState() const { return nState; }
|
int GetState() const { return nState; }
|
||||||
std::string GetStateString() const;
|
std::string GetStateString() const;
|
||||||
|
|
||||||
int GetEntriesCount() const { return vecEntries.size(); }
|
int GetEntriesCount() const { LOCK(cs_coinjoin); return vecEntries.size(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// base class
|
// base class
|
||||||
@ -376,7 +376,7 @@ protected:
|
|||||||
mutable CCriticalSection cs_vecqueue;
|
mutable CCriticalSection cs_vecqueue;
|
||||||
|
|
||||||
// The current mixing sessions in progress on the network
|
// The current mixing sessions in progress on the network
|
||||||
std::vector<CCoinJoinQueue> vecCoinJoinQueue;
|
std::vector<CCoinJoinQueue> vecCoinJoinQueue GUARDED_BY(cs_vecqueue);
|
||||||
|
|
||||||
void SetNull();
|
void SetNull();
|
||||||
void CheckQueue();
|
void CheckQueue();
|
||||||
@ -385,7 +385,7 @@ public:
|
|||||||
CCoinJoinBaseManager() :
|
CCoinJoinBaseManager() :
|
||||||
vecCoinJoinQueue() {}
|
vecCoinJoinQueue() {}
|
||||||
|
|
||||||
int GetQueueSize() const { return vecCoinJoinQueue.size(); }
|
int GetQueueSize() const { LOCK(cs_vecqueue); return vecCoinJoinQueue.size(); }
|
||||||
bool GetQueueItemAndTry(CCoinJoinQueue& dsqRet);
|
bool GetQueueItemAndTry(CCoinJoinQueue& dsqRet);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user