2019-01-29 15:53:14 +01:00
// Copyright (c) 2014-2019 The Dash Core developers
2017-05-05 13:26:27 +02:00
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2018-11-05 10:29:33 +01:00
2017-05-05 13:26:27 +02:00
# include "privatesend.h"
2019-05-21 15:26:15 +02:00
# include "masternode/activemasternode.h"
2017-05-05 13:26:27 +02:00
# include "consensus/validation.h"
2019-05-21 15:26:15 +02:00
# include "masternode/masternode-payments.h"
# include "masternode/masternode-sync.h"
2017-05-05 13:26:27 +02:00
# include "messagesigner.h"
2016-11-25 20:01:56 +01:00
# include "netmessagemaker.h"
2017-05-05 13:26:27 +02:00
# include "script/sign.h"
# include "txmempool.h"
# include "util.h"
# include "utilmoneystr.h"
2019-01-03 21:08:34 +01:00
# include "validation.h"
2017-05-05 13:26:27 +02:00
2019-04-29 10:32:08 +02:00
# include "llmq/quorums_instantsend.h"
2018-07-12 11:02:20 +02:00
# include <string>
2017-05-05 13:26:27 +02:00
2018-10-25 16:31:32 +02:00
bool CPrivateSendEntry : : AddScriptSig ( const CTxIn & txin )
2017-05-05 13:26:27 +02:00
{
2018-02-06 12:09:33 +01:00
for ( auto & txdsin : vecTxDSIn ) {
2018-11-05 10:29:07 +01:00
if ( txdsin . prevout = = txin . prevout & & txdsin . nSequence = = txin . nSequence ) {
if ( txdsin . fHasSig ) return false ;
2017-05-05 13:26:27 +02:00
txdsin . scriptSig = txin . scriptSig ;
txdsin . fHasSig = true ;
return true ;
}
}
return false ;
}
2018-10-25 16:31:32 +02:00
uint256 CPrivateSendQueue : : GetSignatureHash ( ) const
2018-02-16 15:54:53 +01:00
{
2019-01-03 10:17:43 +01:00
return SerializeHash ( * this ) ;
2018-02-16 15:54:53 +01:00
}
2018-10-25 16:31:32 +02:00
bool CPrivateSendQueue : : Sign ( )
2017-05-05 13:26:27 +02:00
{
2018-11-05 10:29:07 +01:00
if ( ! fMasternodeMode ) return false ;
2017-05-05 13:26:27 +02:00
2018-02-16 15:54:53 +01:00
2018-12-17 15:00:10 +01:00
uint256 hash = GetSignatureHash ( ) ;
CBLSSignature sig = activeMasternodeInfo . blsKeyOperator - > Sign ( hash ) ;
if ( ! sig . IsValid ( ) ) {
return false ;
2017-06-30 20:30:16 +02:00
}
2018-12-17 15:00:10 +01:00
sig . GetBuf ( vchSig ) ;
2017-06-30 20:30:16 +02:00
2018-02-16 15:54:53 +01:00
return true ;
2017-06-30 20:30:16 +02:00
}
2018-12-17 15:00:10 +01:00
bool CPrivateSendQueue : : CheckSignature ( const CBLSPublicKey & blsPubKey ) const
2017-06-30 20:30:16 +02:00
{
2018-12-17 15:00:10 +01:00
uint256 hash = GetSignatureHash ( ) ;
2017-06-30 20:30:16 +02:00
2018-12-17 15:00:10 +01:00
CBLSSignature sig ;
sig . SetBuf ( vchSig ) ;
if ( ! sig . IsValid ( ) | | ! sig . VerifyInsecure ( blsPubKey , hash ) ) {
LogPrintf ( " CTxLockVote::CheckSignature -- VerifyInsecure() failed \n " ) ;
return false ;
2017-06-30 20:30:16 +02:00
}
return true ;
}
2018-10-25 16:31:32 +02:00
bool CPrivateSendQueue : : Relay ( CConnman & connman )
2017-06-30 20:30:16 +02:00
{
2018-02-06 12:09:33 +01:00
connman . ForEachNode ( [ & connman , this ] ( CNode * pnode ) {
2016-11-25 20:01:56 +01:00
CNetMsgMaker msgMaker ( pnode - > GetSendVersion ( ) ) ;
2019-03-21 09:33:41 +01:00
if ( pnode - > nVersion > = MIN_PRIVATESEND_PEER_PROTO_VERSION & & pnode - > fSendDSQueue )
2016-11-25 20:01:56 +01:00
connman . PushMessage ( pnode , msgMaker . Make ( NetMsgType : : DSQUEUE , ( * this ) ) ) ;
2018-02-06 12:09:33 +01:00
} ) ;
2017-06-30 20:30:16 +02:00
return true ;
2017-05-05 13:26:27 +02:00
}
2018-10-25 16:31:32 +02:00
uint256 CPrivateSendBroadcastTx : : GetSignatureHash ( ) const
2018-02-16 15:54:53 +01:00
{
return SerializeHash ( * this ) ;
}
2018-10-25 16:31:32 +02:00
bool CPrivateSendBroadcastTx : : Sign ( )
2017-06-30 20:30:16 +02:00
{
2018-11-05 10:29:07 +01:00
if ( ! fMasternodeMode ) return false ;
2017-06-30 20:30:16 +02:00
2018-02-16 15:54:53 +01:00
2018-12-17 13:40:29 +01:00
uint256 hash = GetSignatureHash ( ) ;
2017-06-30 20:30:16 +02:00
2018-12-17 13:40:29 +01:00
CBLSSignature sig = activeMasternodeInfo . blsKeyOperator - > Sign ( hash ) ;
if ( ! sig . IsValid ( ) ) {
return false ;
2017-06-30 20:30:16 +02:00
}
2018-12-17 13:40:29 +01:00
sig . GetBuf ( vchSig ) ;
2017-06-30 20:30:16 +02:00
2018-02-16 15:54:53 +01:00
return true ;
2017-06-30 20:30:16 +02:00
}
2018-12-17 13:40:29 +01:00
bool CPrivateSendBroadcastTx : : CheckSignature ( const CBLSPublicKey & blsPubKey ) const
2017-06-30 20:30:16 +02:00
{
2018-12-17 13:40:29 +01:00
uint256 hash = GetSignatureHash ( ) ;
2018-02-16 15:54:53 +01:00
2018-12-17 13:40:29 +01:00
CBLSSignature sig ;
sig . SetBuf ( vchSig ) ;
if ( ! sig . IsValid ( ) | | ! sig . VerifyInsecure ( blsPubKey , hash ) ) {
LogPrintf ( " CTxLockVote::CheckSignature -- VerifyInsecure() failed \n " ) ;
return false ;
2017-06-30 20:30:16 +02:00
}
return true ;
}
2018-10-25 16:31:32 +02:00
bool CPrivateSendBroadcastTx : : IsExpired ( int nHeight )
2017-07-10 16:42:09 +02:00
{
// expire confirmed DSTXes after ~1h since confirmation
return ( nConfirmedHeight ! = - 1 ) & & ( nHeight - nConfirmedHeight > 24 ) ;
}
2019-05-23 11:13:34 +02:00
bool CPrivateSendBroadcastTx : : IsValidStructure ( )
{
// some trivial checks only
if ( tx - > vin . size ( ) ! = tx - > vout . size ( ) ) {
return false ;
}
if ( tx - > vin . size ( ) < CPrivateSend : : GetMinPoolParticipants ( ) ) {
return false ;
}
if ( tx - > vin . size ( ) > CPrivateSend : : GetMaxPoolParticipants ( ) * PRIVATESEND_ENTRY_MAX_SIZE ) {
return false ;
}
for ( const auto & out : tx - > vout ) {
if ( ! CPrivateSend : : IsDenominatedAmount ( out . nValue ) ) {
return false ;
}
if ( ! out . scriptPubKey . IsPayToPublicKeyHash ( ) ) {
return false ;
}
}
return true ;
}
2018-09-04 12:54:59 +02:00
void CPrivateSendBaseSession : : SetNull ( )
2017-05-05 13:26:27 +02:00
{
// Both sides
2018-10-25 16:31:32 +02:00
LOCK ( cs_privatesend ) ;
2017-05-05 13:26:27 +02:00
nState = POOL_STATE_IDLE ;
nSessionID = 0 ;
nSessionDenom = 0 ;
vecEntries . clear ( ) ;
finalMutableTransaction . vin . clear ( ) ;
finalMutableTransaction . vout . clear ( ) ;
2018-02-12 13:47:53 +01:00
nTimeLastSuccessfulStep = GetTime ( ) ;
2017-05-05 13:26:27 +02:00
}
2018-09-04 12:54:59 +02:00
void CPrivateSendBaseManager : : SetNull ( )
2017-12-04 07:06:07 +01:00
{
2018-09-04 12:54:59 +02:00
LOCK ( cs_vecqueue ) ;
2018-10-25 16:31:32 +02:00
vecPrivateSendQueue . clear ( ) ;
2018-09-04 12:54:59 +02:00
}
void CPrivateSendBaseManager : : CheckQueue ( )
{
TRY_LOCK ( cs_vecqueue , lockDS ) ;
2018-11-05 10:29:07 +01:00
if ( ! lockDS ) return ; // it's ok to fail here, we run this quite frequently
2017-12-04 07:06:07 +01:00
// check mixing queue objects for timeouts
2018-10-25 16:31:32 +02:00
std : : vector < CPrivateSendQueue > : : iterator it = vecPrivateSendQueue . begin ( ) ;
2018-11-05 10:29:07 +01:00
while ( it ! = vecPrivateSendQueue . end ( ) ) {
if ( ( * it ) . IsExpired ( ) ) {
2019-05-22 23:51:39 +02:00
LogPrint ( BCLog : : PRIVATESEND , " CPrivateSendBaseManager::%s -- Removing expired queue (%s) \n " , __func__ , ( * it ) . ToString ( ) ) ;
2018-10-25 16:31:32 +02:00
it = vecPrivateSendQueue . erase ( it ) ;
2018-11-05 10:29:07 +01:00
} else
+ + it ;
2017-12-04 07:06:07 +01:00
}
}
2018-10-25 16:31:32 +02:00
bool CPrivateSendBaseManager : : GetQueueItemAndTry ( CPrivateSendQueue & dsqRet )
2018-09-04 12:54:59 +02:00
{
TRY_LOCK ( cs_vecqueue , lockDS ) ;
2018-11-05 10:29:07 +01:00
if ( ! lockDS ) return false ; // it's ok to fail here, we run this quite frequently
2018-09-04 12:54:59 +02:00
2018-10-25 16:31:32 +02:00
for ( auto & dsq : vecPrivateSendQueue ) {
2018-09-04 12:54:59 +02:00
// only try each queue once
2018-11-05 10:29:07 +01:00
if ( dsq . fTried | | dsq . IsExpired ( ) ) continue ;
2018-09-04 12:54:59 +02:00
dsq . fTried = true ;
dsqRet = dsq ;
return true ;
}
return false ;
}
std : : string CPrivateSendBaseSession : : GetStateString ( ) const
2017-05-05 13:26:27 +02:00
{
2018-11-05 10:29:07 +01:00
switch ( nState ) {
case POOL_STATE_IDLE :
return " IDLE " ;
case POOL_STATE_QUEUE :
return " QUEUE " ;
case POOL_STATE_ACCEPTING_ENTRIES :
return " ACCEPTING_ENTRIES " ;
case POOL_STATE_SIGNING :
return " SIGNING " ;
case POOL_STATE_ERROR :
return " ERROR " ;
case POOL_STATE_SUCCESS :
return " SUCCESS " ;
default :
return " UNKNOWN " ;
2017-05-05 13:26:27 +02:00
}
}
2017-06-30 20:30:16 +02:00
// Definitions for static data members
std : : vector < CAmount > CPrivateSend : : vecStandardDenominations ;
2018-10-25 16:31:32 +02:00
std : : map < uint256 , CPrivateSendBroadcastTx > CPrivateSend : : mapDSTX ;
2017-06-30 20:30:16 +02:00
CCriticalSection CPrivateSend : : cs_mapdstx ;
void CPrivateSend : : InitStandardDenominations ( )
{
vecStandardDenominations . clear ( ) ;
/* Denominations
2018-02-08 06:46:44 +01:00
A note about convertibility . Within mixing pools , each denomination
is convertible to another .
2017-06-30 20:30:16 +02:00
For example :
1 DRK + 1000 = = ( .1 DRK + 100 ) * 10
10 DRK + 10000 = = ( 1 DRK + 1000 ) * 10
*/
/* Disabled
vecStandardDenominations . push_back ( ( 100 * COIN ) + 100000 ) ;
*/
2018-11-05 10:29:07 +01:00
vecStandardDenominations . push_back ( ( 10 * COIN ) + 10000 ) ;
vecStandardDenominations . push_back ( ( 1 * COIN ) + 1000 ) ;
vecStandardDenominations . push_back ( ( .1 * COIN ) + 100 ) ;
vecStandardDenominations . push_back ( ( .01 * COIN ) + 10 ) ;
2018-11-07 08:39:25 +01:00
vecStandardDenominations . push_back ( ( .001 * COIN ) + 1 ) ;
2017-06-30 20:30:16 +02:00
}
2017-05-05 13:26:27 +02:00
// check to make sure the collateral provided by the client is valid
bool CPrivateSend : : IsCollateralValid ( const CTransaction & txCollateral )
{
2018-11-05 10:29:07 +01:00
if ( txCollateral . vout . empty ( ) ) return false ;
if ( txCollateral . nLockTime ! = 0 ) return false ;
2017-05-05 13:26:27 +02:00
CAmount nValueIn = 0 ;
CAmount nValueOut = 0 ;
2018-02-06 12:09:33 +01:00
for ( const auto & txout : txCollateral . vout ) {
2017-05-05 13:26:27 +02:00
nValueOut + = txout . nValue ;
2018-11-07 08:39:25 +01:00
if ( ! txout . scriptPubKey . IsPayToPublicKeyHash ( ) & & ! txout . scriptPubKey . IsUnspendable ( ) ) {
2018-11-05 10:29:07 +01:00
LogPrintf ( " CPrivateSend::IsCollateralValid -- Invalid Script, txCollateral=%s " , txCollateral . ToString ( ) ) ;
2017-05-05 13:26:27 +02:00
return false ;
}
}
2018-02-06 12:09:33 +01:00
for ( const auto & txin : txCollateral . vin ) {
2017-09-26 16:33:46 +02:00
Coin coin ;
2019-04-29 10:32:08 +02:00
auto mempoolTx = mempool . get ( txin . prevout . hash ) ;
if ( mempoolTx ! = nullptr ) {
if ( mempool . isSpent ( txin . prevout ) | | ! llmq : : quorumInstantSendManager - > IsLocked ( txin . prevout . hash ) ) {
2019-05-22 23:51:39 +02:00
LogPrint ( BCLog : : PRIVATESEND , " CPrivateSend::IsCollateralValid -- spent or non-locked mempool input! txin=%s \n " , txin . ToString ( ) ) ;
2019-04-29 10:32:08 +02:00
return false ;
}
nValueIn + = mempoolTx - > vout [ txin . prevout . n ] . nValue ;
} else if ( GetUTXOCoin ( txin . prevout , coin ) ) {
nValueIn + = coin . out . nValue ;
} else {
2019-05-22 23:51:39 +02:00
LogPrint ( BCLog : : PRIVATESEND , " CPrivateSend::IsCollateralValid -- Unknown inputs in collateral transaction, txCollateral=%s " , txCollateral . ToString ( ) ) ;
2017-08-25 14:56:48 +02:00
return false ;
2017-05-05 13:26:27 +02:00
}
}
2017-06-30 20:30:16 +02:00
//collateral transactions are required to pay out a small fee to the miners
2018-11-05 10:29:07 +01:00
if ( nValueIn - nValueOut < GetCollateralAmount ( ) ) {
2019-05-22 23:51:39 +02:00
LogPrint ( BCLog : : PRIVATESEND , " CPrivateSend::IsCollateralValid -- did not include enough fees in transaction: fees: %d, txCollateral=%s " , nValueOut - nValueIn , txCollateral . ToString ( ) ) ;
2017-05-05 13:26:27 +02:00
return false ;
}
2019-05-22 23:51:39 +02:00
LogPrint ( BCLog : : PRIVATESEND , " CPrivateSend::IsCollateralValid -- %s " , txCollateral . ToString ( ) ) ;
2017-05-05 13:26:27 +02:00
{
LOCK ( cs_main ) ;
CValidationState validationState ;
2018-11-05 10:29:07 +01:00
if ( ! AcceptToMemoryPool ( mempool , validationState , MakeTransactionRef ( txCollateral ) , false , NULL , false , maxTxFee , true ) ) {
2019-05-22 23:51:39 +02:00
LogPrint ( BCLog : : PRIVATESEND , " CPrivateSend::IsCollateralValid -- didn't pass AcceptToMemoryPool() \n " ) ;
2017-05-05 13:26:27 +02:00
return false ;
}
}
return true ;
}
2017-12-04 07:06:07 +01:00
bool CPrivateSend : : IsCollateralAmount ( CAmount nInputAmount )
{
2018-11-07 08:39:25 +01:00
// collateral input can be anything between 1x and "max" (including both)
return ( nInputAmount > = GetCollateralAmount ( ) & & nInputAmount < = GetMaxCollateralAmount ( ) ) ;
2017-12-04 07:06:07 +01:00
}
2017-05-05 13:26:27 +02:00
/* Create a nice string to show the denominations
Function returns as follows ( for 4 denominations ) :
( bit on if present )
2018-02-08 06:46:44 +01:00
bit 0 - 10
bit 1 - 1
bit 2 - .1
bit 3 - .01
2017-05-05 13:26:27 +02:00
bit 4 and so on - out - of - bounds
none of above - non - denom
*/
std : : string CPrivateSend : : GetDenominationsToString ( int nDenom )
{
std : : string strDenom = " " ;
2017-06-30 20:30:16 +02:00
int nMaxDenoms = vecStandardDenominations . size ( ) ;
2017-05-05 13:26:27 +02:00
2018-11-05 10:29:07 +01:00
if ( nDenom > = ( 1 < < nMaxDenoms ) ) {
2017-05-05 13:26:27 +02:00
return " out-of-bounds " ;
}
for ( int i = 0 ; i < nMaxDenoms ; + + i ) {
2018-11-05 10:29:07 +01:00
if ( nDenom & ( 1 < < i ) ) {
2017-06-30 20:30:16 +02:00
strDenom + = ( strDenom . empty ( ) ? " " : " + " ) + FormatMoney ( vecStandardDenominations [ i ] ) ;
2017-05-05 13:26:27 +02:00
}
}
2018-11-05 10:29:07 +01:00
if ( strDenom . empty ( ) ) {
2017-05-05 13:26:27 +02:00
return " non-denom " ;
}
return strDenom ;
}
/* Return a bitshifted integer representing the denominations in this list
Function returns as follows ( for 4 denominations ) :
( bit on if present )
2018-02-08 06:46:44 +01:00
10 - bit 0
1 - bit 1
.1 - bit 2
.01 - bit 3
2017-05-05 13:26:27 +02:00
non - denom - 0 , all bits off
*/
int CPrivateSend : : GetDenominations ( const std : : vector < CTxOut > & vecTxOut , bool fSingleRandomDenom )
{
std : : vector < std : : pair < CAmount , int > > vecDenomUsed ;
// make a list of denominations, with zero uses
2018-02-06 12:09:33 +01:00
for ( const auto & nDenomValue : vecStandardDenominations )
2017-05-05 13:26:27 +02:00
vecDenomUsed . push_back ( std : : make_pair ( nDenomValue , 0 ) ) ;
// look for denominations and update uses to 1
2018-02-06 12:09:33 +01:00
for ( const auto & txout : vecTxOut ) {
2017-05-05 13:26:27 +02:00
bool found = false ;
2018-02-06 12:09:33 +01:00
for ( auto & s : vecDenomUsed ) {
2018-11-05 10:29:07 +01:00
if ( txout . nValue = = s . first ) {
2017-05-05 13:26:27 +02:00
s . second = 1 ;
found = true ;
}
}
2018-11-05 10:29:07 +01:00
if ( ! found ) return 0 ;
2017-05-05 13:26:27 +02:00
}
int nDenom = 0 ;
int c = 0 ;
// if the denomination is used, shift the bit on
2018-02-06 12:09:33 +01:00
for ( const auto & s : vecDenomUsed ) {
2017-05-05 13:26:27 +02:00
int bit = ( fSingleRandomDenom ? GetRandInt ( 2 ) : 1 ) & s . second ;
nDenom | = bit < < c + + ;
2018-11-05 10:29:07 +01:00
if ( fSingleRandomDenom & & bit ) break ; // use just one random denomination
2017-05-05 13:26:27 +02:00
}
return nDenom ;
}
2018-11-05 10:29:07 +01:00
bool CPrivateSend : : GetDenominationsBits ( int nDenom , std : : vector < int > & vecBitsRet )
2017-05-05 13:26:27 +02:00
{
// ( bit on if present, 4 denominations example )
// bit 0 - 100DASH+1
// bit 1 - 10DASH+1
// bit 2 - 1DASH+1
// bit 3 - .1DASH+1
2017-06-30 20:30:16 +02:00
int nMaxDenoms = vecStandardDenominations . size ( ) ;
2017-05-05 13:26:27 +02:00
2018-11-05 10:29:07 +01:00
if ( nDenom > = ( 1 < < nMaxDenoms ) ) return false ;
2017-05-05 13:26:27 +02:00
vecBitsRet . clear ( ) ;
for ( int i = 0 ; i < nMaxDenoms ; + + i ) {
2018-11-05 10:29:07 +01:00
if ( nDenom & ( 1 < < i ) ) {
2017-05-05 13:26:27 +02:00
vecBitsRet . push_back ( i ) ;
}
}
return ! vecBitsRet . empty ( ) ;
}
int CPrivateSend : : GetDenominationsByAmounts ( const std : : vector < CAmount > & vecAmount )
{
CScript scriptTmp = CScript ( ) ;
std : : vector < CTxOut > vecTxOut ;
2018-07-12 11:07:51 +02:00
for ( auto it = vecAmount . rbegin ( ) ; it ! = vecAmount . rend ( ) ; + + it ) {
CTxOut txout ( ( * it ) , scriptTmp ) ;
2017-05-05 13:26:27 +02:00
vecTxOut . push_back ( txout ) ;
}
return GetDenominations ( vecTxOut , true ) ;
}
2017-12-04 07:06:07 +01:00
bool CPrivateSend : : IsDenominatedAmount ( CAmount nInputAmount )
{
for ( const auto & nDenomValue : vecStandardDenominations )
2018-11-05 10:29:07 +01:00
if ( nInputAmount = = nDenomValue )
2017-12-04 07:06:07 +01:00
return true ;
return false ;
}
2017-05-05 13:26:27 +02:00
std : : string CPrivateSend : : GetMessageByID ( PoolMessage nMessageID )
{
switch ( nMessageID ) {
2018-11-05 10:29:07 +01:00
case ERR_ALREADY_HAVE :
return _ ( " Already have that input. " ) ;
case ERR_DENOM :
return _ ( " No matching denominations found for mixing. " ) ;
case ERR_ENTRIES_FULL :
return _ ( " Entries are full. " ) ;
case ERR_EXISTING_TX :
return _ ( " Not compatible with existing transactions. " ) ;
case ERR_FEES :
return _ ( " Transaction fees are too high. " ) ;
case ERR_INVALID_COLLATERAL :
return _ ( " Collateral not valid. " ) ;
case ERR_INVALID_INPUT :
return _ ( " Input is not valid. " ) ;
case ERR_INVALID_SCRIPT :
return _ ( " Invalid script detected. " ) ;
case ERR_INVALID_TX :
return _ ( " Transaction not valid. " ) ;
case ERR_MAXIMUM :
return _ ( " Entry exceeds maximum size. " ) ;
case ERR_MN_LIST :
return _ ( " Not in the Masternode list. " ) ;
case ERR_MODE :
return _ ( " Incompatible mode. " ) ;
case ERR_NON_STANDARD_PUBKEY :
return _ ( " Non-standard public key detected. " ) ;
case ERR_NOT_A_MN :
return _ ( " This is not a Masternode. " ) ; // not used
case ERR_QUEUE_FULL :
return _ ( " Masternode queue is full. " ) ;
case ERR_RECENT :
return _ ( " Last PrivateSend was too recent. " ) ;
case ERR_SESSION :
return _ ( " Session not complete! " ) ;
case ERR_MISSING_TX :
return _ ( " Missing input transaction information. " ) ;
case ERR_VERSION :
return _ ( " Incompatible version. " ) ;
case MSG_NOERR :
return _ ( " No errors detected. " ) ;
case MSG_SUCCESS :
return _ ( " Transaction created successfully. " ) ;
case MSG_ENTRIES_ADDED :
return _ ( " Your entries added successfully. " ) ;
2019-05-23 11:13:34 +02:00
case ERR_SIZE_MISMATCH :
return _ ( " Inputs vs outputs size mismatch. " ) ;
2018-11-05 10:29:07 +01:00
default :
return _ ( " Unknown response. " ) ;
2017-05-05 13:26:27 +02:00
}
}
2018-10-25 16:31:32 +02:00
void CPrivateSend : : AddDSTX ( const CPrivateSendBroadcastTx & dstx )
2017-05-05 13:26:27 +02:00
{
2017-06-30 20:30:16 +02:00
LOCK ( cs_mapdstx ) ;
2017-09-20 14:02:53 +02:00
mapDSTX . insert ( std : : make_pair ( dstx . tx - > GetHash ( ) , dstx ) ) ;
2017-05-05 13:26:27 +02:00
}
2018-10-25 16:31:32 +02:00
CPrivateSendBroadcastTx CPrivateSend : : GetDSTX ( const uint256 & hash )
2017-05-05 13:26:27 +02:00
{
2017-06-30 20:30:16 +02:00
LOCK ( cs_mapdstx ) ;
auto it = mapDSTX . find ( hash ) ;
2018-10-25 16:31:32 +02:00
return ( it = = mapDSTX . end ( ) ) ? CPrivateSendBroadcastTx ( ) : it - > second ;
2017-05-05 13:26:27 +02:00
}
2017-07-10 16:42:09 +02:00
void CPrivateSend : : CheckDSTXes ( int nHeight )
{
LOCK ( cs_mapdstx ) ;
2018-10-25 16:31:32 +02:00
std : : map < uint256 , CPrivateSendBroadcastTx > : : iterator it = mapDSTX . begin ( ) ;
2018-11-05 10:29:07 +01:00
while ( it ! = mapDSTX . end ( ) ) {
2017-07-10 16:42:09 +02:00
if ( it - > second . IsExpired ( nHeight ) ) {
mapDSTX . erase ( it + + ) ;
} else {
+ + it ;
}
}
2019-05-22 23:51:39 +02:00
LogPrint ( BCLog : : PRIVATESEND , " CPrivateSend::CheckDSTXes -- mapDSTX.size()=%llu \n " , mapDSTX . size ( ) ) ;
2017-07-10 16:42:09 +02:00
}
2018-11-05 10:29:07 +01:00
void CPrivateSend : : UpdatedBlockTip ( const CBlockIndex * pindex )
2017-12-07 10:42:47 +01:00
{
2019-01-03 10:17:43 +01:00
if ( pindex & & ! fLiteMode & & masternodeSync . IsBlockchainSynced ( ) ) {
2017-12-07 10:42:47 +01:00
CheckDSTXes ( pindex - > nHeight ) ;
}
}
2019-05-27 16:22:09 +02:00
void CPrivateSend : : UpdateDSTXConfirmedHeight ( const CTransactionRef & tx , int nHeight )
2017-07-10 16:42:09 +02:00
{
2019-05-27 16:22:09 +02:00
AssertLockHeld ( cs_mapdstx ) ;
2017-07-10 16:42:09 +02:00
2019-05-23 18:22:37 +02:00
uint256 txHash = tx - > GetHash ( ) ;
2017-07-10 16:42:09 +02:00
if ( ! mapDSTX . count ( txHash ) ) return ;
2019-05-27 16:22:09 +02:00
mapDSTX [ txHash ] . SetConfirmedHeight ( nHeight ) ;
LogPrint ( BCLog : : PRIVATESEND , " CPrivateSend::%s -- txid=%s, nHeight=%d \n " , __func__ , txHash . ToString ( ) , nHeight ) ;
}
void CPrivateSend : : TransactionAddedToMempool ( const CTransactionRef & tx )
{
LOCK ( cs_mapdstx ) ;
UpdateDSTXConfirmedHeight ( tx , - 1 ) ;
}
void CPrivateSend : : BlockConnected ( const std : : shared_ptr < const CBlock > & pblock , const CBlockIndex * pindex , const std : : vector < CTransactionRef > & vtxConflicted )
{
LOCK ( cs_mapdstx ) ;
for ( const auto & tx : vtxConflicted ) {
UpdateDSTXConfirmedHeight ( tx , - 1 ) ;
}
for ( const auto & tx : pblock - > vtx ) {
UpdateDSTXConfirmedHeight ( tx , pindex - > nHeight ) ;
}
}
void CPrivateSend : : BlockDisconnected ( const std : : shared_ptr < const CBlock > & pblock , const CBlockIndex * pindexDisconnected )
{
LOCK ( cs_mapdstx ) ;
for ( const auto & tx : pblock - > vtx ) {
UpdateDSTXConfirmedHeight ( tx , - 1 ) ;
}
2017-07-10 16:42:09 +02:00
}