diff --git a/src/instantx.cpp b/src/instantx.cpp index 26ff0ba582..4bed1da594 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -91,7 +91,7 @@ bool CInstantSend::ProcessTxLockRequest(const CTxLockRequest& txLockRequest, CCo uint256 txHash = txLockRequest.GetHash(); // Check to see if we conflict with existing completed lock - BOOST_FOREACH(const CTxIn& txin, txLockRequest.vin) { + BOOST_FOREACH(const CTxIn& txin, txLockRequest.tx->vin) { std::map::iterator it = mapLockedOutpoints.find(txin.prevout); if(it != mapLockedOutpoints.end() && it->second != txLockRequest.GetHash()) { // Conflicting with complete lock, proceed to see if we should cancel them both @@ -102,7 +102,7 @@ bool CInstantSend::ProcessTxLockRequest(const CTxLockRequest& txLockRequest, CCo // Check to see if there are votes for conflicting request, // if so - do not fail, just warn user - BOOST_FOREACH(const CTxIn& txin, txLockRequest.vin) { + BOOST_FOREACH(const CTxIn& txin, txLockRequest.tx->vin) { std::map >::iterator it = mapVotedOutpoints.find(txin.prevout); if(it != mapVotedOutpoints.end()) { BOOST_FOREACH(const uint256& hash, it->second) { @@ -145,7 +145,7 @@ bool CInstantSend::CreateTxLockCandidate(const CTxLockRequest& txLockRequest) CTxLockCandidate txLockCandidate(txLockRequest); // all inputs should already be checked by txLockRequest.IsValid() above, just use them now - BOOST_REVERSE_FOREACH(const CTxIn& txin, txLockRequest.vin) { + BOOST_REVERSE_FOREACH(const CTxIn& txin, txLockRequest.tx->vin) { txLockCandidate.AddOutPointLock(txin.prevout); } mapTxLockCandidates.insert(std::make_pair(txHash, txLockCandidate)); @@ -159,7 +159,7 @@ bool CInstantSend::CreateTxLockCandidate(const CTxLockRequest& txLockRequest) LogPrintf("CInstantSend::CreateTxLockCandidate -- update empty, txid=%s\n", txHash.ToString()); // all inputs should already be checked by txLockRequest.IsValid() above, just use them now - BOOST_REVERSE_FOREACH(const CTxIn& txin, txLockRequest.vin) { + BOOST_REVERSE_FOREACH(const CTxIn& txin, txLockRequest.tx->vin) { itLockCandidate->second.AddOutPointLock(txin.prevout); } } else { @@ -446,7 +446,7 @@ bool CInstantSend::IsEnoughOrphanVotesForTx(const CTxLockRequest& txLockRequest) // There could be a situation when we already have quite a lot of votes // but tx lock request still wasn't received. Let's scan through // orphan votes to check if this is the case. - BOOST_FOREACH(const CTxIn& txin, txLockRequest.vin) { + BOOST_FOREACH(const CTxIn& txin, txLockRequest.tx->vin) { if(!IsEnoughOrphanVotesForTxAndOutPoint(txLockRequest.GetHash(), txin.prevout)) { return false; } @@ -483,7 +483,7 @@ void CInstantSend::TryToFinalizeLockCandidate(const CTxLockCandidate& txLockCand #endif LOCK(cs_instantsend); - uint256 txHash = txLockCandidate.txLockRequest.GetHash(); + uint256 txHash = txLockCandidate.txLockRequest.tx->GetHash(); if(txLockCandidate.IsAllOutPointsReady() && !IsLockedInstantSendTransaction(txHash)) { // we have enough votes now LogPrint("instantsend", "CInstantSend::TryToFinalizeLockCandidate -- Transaction Lock is ready to complete, txid=%s\n", txHash.ToString()); @@ -520,7 +520,7 @@ void CInstantSend::UpdateLockedTransaction(const CTxLockCandidate& txLockCandida } #endif - GetMainSignals().NotifyTransactionLock(txLockCandidate.txLockRequest); + GetMainSignals().NotifyTransactionLock(*txLockCandidate.txLockRequest.tx); LogPrint("instantsend", "CInstantSend::UpdateLockedTransaction -- done, txid=%s\n", txHash.ToString()); } @@ -564,7 +564,7 @@ bool CInstantSend::ResolveConflicts(const CTxLockCandidate& txLockCandidate) LOCK(mempool.cs); // protect mempool.mapNextTx - BOOST_FOREACH(const CTxIn& txin, txLockCandidate.txLockRequest.vin) { + BOOST_FOREACH(const CTxIn& txin, txLockCandidate.txLockRequest.tx->vin) { uint256 hashConflicting; if(GetLockedOutPointTxHash(txin.prevout, hashConflicting) && txHash != hashConflicting) { // completed lock which conflicts with another completed one? @@ -615,7 +615,7 @@ bool CInstantSend::ResolveConflicts(const CTxLockCandidate& txLockCandidate) return true; } // Not in block yet, make sure all its inputs are still unspent - BOOST_FOREACH(const CTxIn& txin, txLockCandidate.txLockRequest.vin) { + BOOST_FOREACH(const CTxIn& txin, txLockCandidate.txLockRequest.tx->vin) { Coin coin; if(!GetUTXOCoin(txin.prevout, coin)) { // Not in UTXO anymore? A conflicting tx was mined while we were waiting for votes. @@ -927,21 +927,21 @@ std::string CInstantSend::ToString() bool CTxLockRequest::IsValid() const { - if(vout.size() < 1) return false; + if(tx->vout.size() < 1) return false; - if(vin.size() > WARN_MANY_INPUTS) { + if(tx->vin.size() > WARN_MANY_INPUTS) { LogPrint("instantsend", "CTxLockRequest::IsValid -- WARNING: Too many inputs: tx=%s", ToString()); } LOCK(cs_main); - if(!CheckFinalTx(*this)) { + if(!CheckFinalTx(*tx)) { LogPrint("instantsend", "CTxLockRequest::IsValid -- Transaction is not final: tx=%s", ToString()); return false; } CAmount nValueIn = 0; - BOOST_FOREACH(const CTxIn& txin, vin) { + BOOST_FOREACH(const CTxIn& txin, tx->vin) { Coin coin; @@ -968,7 +968,7 @@ bool CTxLockRequest::IsValid() const return false; } - CAmount nValueOut = GetValueOut(); + CAmount nValueOut = tx->GetValueOut(); if(nValueIn - nValueOut < GetMinFee()) { LogPrint("instantsend", "CTxLockRequest::IsValid -- did not include enough fees in transaction: fees=%d, tx=%s", nValueOut - nValueIn, ToString()); @@ -981,12 +981,12 @@ bool CTxLockRequest::IsValid() const CAmount CTxLockRequest::GetMinFee() const { CAmount nMinFee = MIN_FEE; - return std::max(nMinFee, CAmount(vin.size() * nMinFee)); + return std::max(nMinFee, CAmount(tx->vin.size() * nMinFee)); } int CTxLockRequest::GetMaxSignatures() const { - return vin.size() * COutPointLock::SIGNATURES_TOTAL; + return tx->vin.size() * COutPointLock::SIGNATURES_TOTAL; } // @@ -1204,7 +1204,7 @@ bool CTxLockCandidate::IsTimedOut() const void CTxLockCandidate::Relay(CConnman& connman) const { - connman.RelayTransaction(txLockRequest); + connman.RelayTransaction(*txLockRequest.tx); std::map::const_iterator itOutpointLock = mapOutPointLocks.begin(); while(itOutpointLock != mapOutPointLocks.end()) { itOutpointLock->second.Relay(connman); diff --git a/src/instantx.h b/src/instantx.h index f18d7aac19..b51825800c 100644 --- a/src/instantx.h +++ b/src/instantx.h @@ -119,7 +119,7 @@ public: std::string ToString(); }; -class CTxLockRequest : public CTransaction +class CTxLockRequest { private: static const CAmount MIN_FEE = 0.0001 * COIN; @@ -127,13 +127,40 @@ private: public: static const int WARN_MANY_INPUTS = 100; - CTxLockRequest() = default; - CTxLockRequest(const CTransaction& tx) : CTransaction(tx) {}; + CTransactionRef tx; + + CTxLockRequest() : tx(MakeTransactionRef()) {} + CTxLockRequest(const CTransaction& _tx) : tx(MakeTransactionRef(_tx)) {}; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(tx); + } bool IsValid() const; CAmount GetMinFee() const; int GetMaxSignatures() const; + const uint256 &GetHash() const { + return tx->GetHash(); + } + + std::string ToString() const { + return tx->ToString(); + } + + friend bool operator==(const CTxLockRequest& a, const CTxLockRequest& b) + { + return *a.tx == *b.tx; + } + + friend bool operator!=(const CTxLockRequest& a, const CTxLockRequest& b) + { + return *a.tx != *b.tx; + } + explicit operator bool() const { return *this != CTxLockRequest(); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 68a9dbd9b7..92513f77c2 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1621,11 +1621,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, vRecv >> tx; } else if(strCommand == NetMsgType::TXLOCKREQUEST) { vRecv >> txLockRequest; - tx = txLockRequest; + tx = *txLockRequest.tx; nInvType = MSG_TXLOCK_REQUEST; } else if (strCommand == NetMsgType::DSTX) { vRecv >> dstx; - tx = dstx.tx; + tx = *dstx.tx; nInvType = MSG_DSTX; } diff --git a/src/privatesend-server.cpp b/src/privatesend-server.cpp index 587075c7f0..1a222deae5 100644 --- a/src/privatesend-server.cpp +++ b/src/privatesend-server.cpp @@ -146,7 +146,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, std::string& strCommand, C CDarkSendEntry entry; vRecv >> entry; - LogPrint("privatesend", "DSVIN -- txCollateral %s", entry.txCollateral.ToString()); + LogPrint("privatesend", "DSVIN -- txCollateral %s", entry.txCollateral->ToString()); if(entry.vecTxDSIn.size() > PRIVATESEND_ENTRY_MAX_SIZE) { LogPrintf("DSVIN -- ERROR: too many inputs! %d/%d\n", entry.vecTxDSIn.size(), PRIVATESEND_ENTRY_MAX_SIZE); @@ -398,13 +398,13 @@ void CPrivateSendServer::ChargeFees(CConnman& connman) //we don't need to charge collateral for every offence. if(GetRandInt(100) > 33) return; - std::vector vecOffendersCollaterals; + std::vector vecOffendersCollaterals; if(nState == POOL_STATE_ACCEPTING_ENTRIES) { - BOOST_FOREACH(const CTransaction& txCollateral, vecSessionCollaterals) { + BOOST_FOREACH(CTransactionRef txCollateral, vecSessionCollaterals) { bool fFound = false; BOOST_FOREACH(const CDarkSendEntry& entry, vecEntries) - if(entry.txCollateral == txCollateral) + if(*entry.txCollateral == *txCollateral) fFound = true; // This queue entry didn't send us the promised transaction @@ -441,17 +441,17 @@ void CPrivateSendServer::ChargeFees(CConnman& connman) if(nState == POOL_STATE_ACCEPTING_ENTRIES || nState == POOL_STATE_SIGNING) { LogPrintf("CPrivateSendServer::ChargeFees -- found uncooperative node (didn't %s transaction), charging fees: %s\n", - (nState == POOL_STATE_SIGNING) ? "sign" : "send", vecOffendersCollaterals[0].ToString()); + (nState == POOL_STATE_SIGNING) ? "sign" : "send", vecOffendersCollaterals[0]->ToString()); LOCK(cs_main); CValidationState state; bool fMissingInputs; - if(!AcceptToMemoryPool(mempool, state, vecOffendersCollaterals[0], false, &fMissingInputs, false, maxTxFee)) { + if(!AcceptToMemoryPool(mempool, state, *vecOffendersCollaterals[0], false, &fMissingInputs, false, maxTxFee)) { // should never really happen LogPrintf("CPrivateSendServer::ChargeFees -- ERROR: AcceptToMemoryPool failed!\n"); } else { - connman.RelayTransaction(vecOffendersCollaterals[0]); + connman.RelayTransaction(*vecOffendersCollaterals[0]); } } } @@ -474,19 +474,19 @@ void CPrivateSendServer::ChargeRandomFees(CConnman& connman) LOCK(cs_main); - BOOST_FOREACH(const CTransaction& txCollateral, vecSessionCollaterals) { + BOOST_FOREACH(CTransactionRef txCollateral, vecSessionCollaterals) { if(GetRandInt(100) > 10) return; - LogPrintf("CPrivateSendServer::ChargeRandomFees -- charging random fees, txCollateral=%s", txCollateral.ToString()); + LogPrintf("CPrivateSendServer::ChargeRandomFees -- charging random fees, txCollateral=%s", txCollateral->ToString()); CValidationState state; bool fMissingInputs; - if(!AcceptToMemoryPool(mempool, state, txCollateral, false, &fMissingInputs, false, maxTxFee)) { + if(!AcceptToMemoryPool(mempool, state, *txCollateral, false, &fMissingInputs, false, maxTxFee)) { // should never really happen LogPrintf("CPrivateSendServer::ChargeRandomFees -- ERROR: AcceptToMemoryPool failed!\n"); } else { - connman.RelayTransaction(txCollateral); + connman.RelayTransaction(*txCollateral); } } } @@ -590,7 +590,7 @@ bool CPrivateSendServer::AddEntry(const CDarkSendEntry& entryNew, PoolMessage& n } } - if(!CPrivateSend::IsCollateralValid(entryNew.txCollateral)) { + if(!CPrivateSend::IsCollateralValid(*entryNew.txCollateral)) { LogPrint("privatesend", "CPrivateSendServer::AddEntry -- collateral not valid!\n"); nMessageIDRet = ERR_INVALID_COLLATERAL; return false; @@ -738,7 +738,7 @@ bool CPrivateSendServer::CreateNewSession(int nDenom, CTransaction txCollateral, vecDarksendQueue.push_back(dsq); } - vecSessionCollaterals.push_back(txCollateral); + vecSessionCollaterals.push_back(MakeTransactionRef(txCollateral)); LogPrintf("CPrivateSendServer::CreateNewSession -- new session created, nSessionID: %d nSessionDenom: %d (%s) vecSessionCollaterals.size(): %d\n", nSessionID, nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), vecSessionCollaterals.size()); @@ -771,7 +771,7 @@ bool CPrivateSendServer::AddUserToExistingSession(int nDenom, CTransaction txCol nMessageIDRet = MSG_NOERR; nTimeLastSuccessfulStep = GetTimeMillis(); - vecSessionCollaterals.push_back(txCollateral); + vecSessionCollaterals.push_back(MakeTransactionRef(txCollateral)); LogPrintf("CPrivateSendServer::AddUserToExistingSession -- new user accepted, nSessionID: %d nSessionDenom: %d (%s) vecSessionCollaterals.size(): %d\n", nSessionID, nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), vecSessionCollaterals.size()); diff --git a/src/privatesend-server.h b/src/privatesend-server.h index 51ef9e3ef7..f6b09c7ff8 100644 --- a/src/privatesend-server.h +++ b/src/privatesend-server.h @@ -20,7 +20,7 @@ class CPrivateSendServer : public CPrivateSendBase private: // Mixing uses collateral transactions to trust parties entering the pool // to behave honestly. If they don't it takes their money. - std::vector vecSessionCollaterals; + std::vector vecSessionCollaterals; bool fUnitTest; diff --git a/src/privatesend.cpp b/src/privatesend.cpp index a5d1228f8c..755f2fb55a 100644 --- a/src/privatesend.cpp +++ b/src/privatesend.cpp @@ -80,7 +80,7 @@ bool CDarksendBroadcastTx::Sign() { if(!fMasterNode) return false; - std::string strMessage = tx.GetHash().ToString() + boost::lexical_cast(sigTime); + std::string strMessage = tx->GetHash().ToString() + boost::lexical_cast(sigTime); if(!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternode.keyMasternode)) { LogPrintf("CDarksendBroadcastTx::Sign -- SignMessage() failed\n"); @@ -92,7 +92,7 @@ bool CDarksendBroadcastTx::Sign() bool CDarksendBroadcastTx::CheckSignature(const CPubKey& pubKeyMasternode) { - std::string strMessage = tx.GetHash().ToString() + boost::lexical_cast(sigTime); + std::string strMessage = tx->GetHash().ToString() + boost::lexical_cast(sigTime); std::string strError = ""; if(!CMessageSigner::VerifyMessage(pubKeyMasternode, vchSig, strMessage, strError)) { @@ -382,7 +382,7 @@ std::string CPrivateSend::GetMessageByID(PoolMessage nMessageID) void CPrivateSend::AddDSTX(const CDarksendBroadcastTx& dstx) { LOCK(cs_mapdstx); - mapDSTX.insert(std::make_pair(dstx.tx.GetHash(), dstx)); + mapDSTX.insert(std::make_pair(dstx.tx->GetHash(), dstx)); } CDarksendBroadcastTx CPrivateSend::GetDSTX(const uint256& hash) diff --git a/src/privatesend.h b/src/privatesend.h index 281fc8f65b..dff95935b1 100644 --- a/src/privatesend.h +++ b/src/privatesend.h @@ -104,21 +104,21 @@ class CDarkSendEntry public: std::vector vecTxDSIn; std::vector vecTxOut; - CTransaction txCollateral; + CTransactionRef txCollateral; // memory only CService addr; CDarkSendEntry() : vecTxDSIn(std::vector()), vecTxOut(std::vector()), - txCollateral(CTransaction()), + txCollateral(MakeTransactionRef()), addr(CService()) {} CDarkSendEntry(const std::vector& vecTxDSIn, const std::vector& vecTxOut, const CTransaction& txCollateral) : vecTxDSIn(vecTxDSIn), vecTxOut(vecTxOut), - txCollateral(txCollateral), + txCollateral(MakeTransactionRef(txCollateral)), addr(CService()) {} @@ -216,25 +216,25 @@ private: int nConfirmedHeight; public: - CTransaction tx; + CTransactionRef tx; CTxIn vin; std::vector vchSig; int64_t sigTime; CDarksendBroadcastTx() : nConfirmedHeight(-1), - tx(), + tx(MakeTransactionRef()), vin(), vchSig(), sigTime(0) {} - CDarksendBroadcastTx(CTransaction tx, COutPoint outpoint, int64_t sigTime) : + CDarksendBroadcastTx(const CTransaction& _tx, COutPoint _outpoint, int64_t _sigTime) : nConfirmedHeight(-1), - tx(tx), - vin(CTxIn(outpoint)), + tx(MakeTransactionRef(_tx)), + vin(CTxIn(_outpoint)), vchSig(), - sigTime(sigTime) + sigTime(_sigTime) {} ADD_SERIALIZE_METHODS; @@ -249,7 +249,7 @@ public: friend bool operator==(const CDarksendBroadcastTx& a, const CDarksendBroadcastTx& b) { - return a.tx == b.tx; + return *a.tx == *b.tx; } friend bool operator!=(const CDarksendBroadcastTx& a, const CDarksendBroadcastTx& b) {