2016-02-02 16:28:56 +01:00
|
|
|
// Copyright (c) 2014-2016 The Dash Core developers
|
2014-12-09 02:17:57 +01:00
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
2015-02-04 14:24:56 +01:00
|
|
|
|
2014-12-09 02:17:57 +01:00
|
|
|
#ifndef DARKSEND_H
|
|
|
|
#define DARKSEND_H
|
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
#include "masternode.h"
|
|
|
|
#include "wallet/wallet.h"
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2015-03-02 00:09:33 +01:00
|
|
|
class CDarksendPool;
|
2014-12-09 02:17:57 +01:00
|
|
|
class CDarkSendSigner;
|
|
|
|
class CDarksendQueue;
|
|
|
|
class CDarksendBroadcastTx;
|
|
|
|
|
2015-03-02 00:09:33 +01:00
|
|
|
// pool states for mixing
|
2016-08-05 21:49:45 +02:00
|
|
|
static const int POOL_STATE_UNKNOWN = 0; // waiting for initialization
|
|
|
|
static const int POOL_STATE_IDLE = 1; // waiting for update
|
|
|
|
static const int POOL_STATE_QUEUE = 2; // waiting in a queue
|
|
|
|
static const int POOL_STATE_ACCEPTING_ENTRIES = 3; // accepting entries
|
|
|
|
static const int POOL_STATE_FINALIZE_TRANSACTION = 4; // master node will broadcast what it accepted
|
|
|
|
static const int POOL_STATE_SIGNING = 5; // check inputs/outputs, sign final tx
|
|
|
|
static const int POOL_STATE_TRANSMISSION = 6; // transmit transaction
|
|
|
|
static const int POOL_STATE_ERROR = 7; // error
|
|
|
|
static const int POOL_STATE_SUCCESS = 8; // success
|
2014-12-09 02:17:57 +01:00
|
|
|
|
|
|
|
// status update message constants
|
2016-08-05 21:49:45 +02:00
|
|
|
static const int MASTERNODE_ACCEPTED = 1;
|
|
|
|
static const int MASTERNODE_REJECTED = 0;
|
|
|
|
static const int MASTERNODE_RESET = -1;
|
|
|
|
|
|
|
|
// timeouts
|
2016-09-01 09:03:47 +02:00
|
|
|
static const int PRIVATESEND_AUTO_TIMEOUT_MIN = 5;
|
|
|
|
static const int PRIVATESEND_AUTO_TIMEOUT_MAX = 15;
|
|
|
|
static const int PRIVATESEND_QUEUE_TIMEOUT = 30;
|
|
|
|
static const int PRIVATESEND_SIGNING_TIMEOUT = 15;
|
2016-08-05 21:49:45 +02:00
|
|
|
|
|
|
|
//! minimum peer version accepted by DarksendPool
|
|
|
|
static const int MIN_PRIVATESEND_PEER_PROTO_VERSION = 70201;
|
|
|
|
|
2016-09-01 09:03:47 +02:00
|
|
|
static const CAmount PRIVATESEND_COLLATERAL = 0.01 * COIN;
|
|
|
|
static const CAmount PRIVATESEND_POOL_MAX = 999.99 * COIN;
|
2016-08-05 21:49:45 +02:00
|
|
|
static const int DENOMS_COUNT_MAX = 100;
|
|
|
|
|
|
|
|
static const int DEFAULT_PRIVATESEND_ROUNDS = 2;
|
|
|
|
static const int DEFAULT_PRIVATESEND_AMOUNT = 1000;
|
|
|
|
static const bool DEFAULT_PRIVATESEND_MULTISESSION = false;
|
|
|
|
|
2016-06-15 21:13:04 +02:00
|
|
|
// Warn user if mixing in gui or try to create backup if mixing in daemon mode
|
|
|
|
// when we have only this many keys left
|
2016-08-05 21:49:45 +02:00
|
|
|
static const int PRIVATESEND_KEYS_THRESHOLD_WARNING = 100;
|
2016-06-15 21:13:04 +02:00
|
|
|
// Stop mixing completely, it's too dangerous to continue when we have only this many keys left
|
2016-08-05 21:49:45 +02:00
|
|
|
static const int PRIVATESEND_KEYS_THRESHOLD_STOP = 50;
|
|
|
|
|
|
|
|
extern int nPrivateSendRounds;
|
|
|
|
extern int nPrivateSendAmount;
|
|
|
|
extern int nLiquidityProvider;
|
|
|
|
extern bool fEnablePrivateSend;
|
|
|
|
extern bool fPrivateSendMultiSession;
|
2015-04-03 00:51:08 +02:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
// The main object for accessing mixing
|
2015-03-02 00:09:33 +01:00
|
|
|
extern CDarksendPool darkSendPool;
|
2016-08-05 21:49:45 +02:00
|
|
|
// A helper object for signing messages from Masternodes
|
2014-12-09 02:17:57 +01:00
|
|
|
extern CDarkSendSigner darkSendSigner;
|
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
extern std::map<uint256, CDarksendBroadcastTx> mapDarksendBroadcastTxes;
|
|
|
|
extern std::vector<CAmount> vecPrivateSendDenominations;
|
|
|
|
|
|
|
|
/** Holds an mixing input
|
2015-03-05 08:49:50 +01:00
|
|
|
*/
|
2015-03-02 00:09:33 +01:00
|
|
|
class CTxDSIn : public CTxIn
|
2014-12-09 02:17:57 +01:00
|
|
|
{
|
|
|
|
public:
|
2015-03-06 08:24:34 +01:00
|
|
|
bool fHasSig; // flag to indicate if signed
|
2015-03-18 18:19:13 +01:00
|
|
|
int nSentTimes; //times we've sent this anonymously
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
CTxDSIn(const CTxIn& txin) :
|
|
|
|
CTxIn(txin),
|
|
|
|
fHasSig(false),
|
2016-08-12 07:43:18 +02:00
|
|
|
nSentTimes(0)
|
|
|
|
{}
|
2016-08-29 21:14:34 +02:00
|
|
|
|
|
|
|
CTxDSIn() :
|
|
|
|
CTxIn(),
|
|
|
|
fHasSig(false),
|
|
|
|
nSentTimes(0)
|
|
|
|
{}
|
2014-12-09 02:17:57 +01:00
|
|
|
};
|
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
/** Holds an mixing output
|
2015-03-06 23:17:51 +01:00
|
|
|
*/
|
|
|
|
class CTxDSOut : public CTxOut
|
|
|
|
{
|
|
|
|
public:
|
2015-03-18 18:19:13 +01:00
|
|
|
int nSentTimes; //times we've sent this anonymously
|
2015-03-06 23:17:51 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
CTxDSOut(const CTxOut& out) :
|
|
|
|
CTxOut(out),
|
2016-08-12 07:43:18 +02:00
|
|
|
nSentTimes(0)
|
|
|
|
{}
|
2016-08-29 21:14:34 +02:00
|
|
|
|
|
|
|
CTxDSOut() :
|
|
|
|
CTxOut(),
|
|
|
|
nSentTimes(0)
|
|
|
|
{}
|
2015-03-06 23:17:51 +01:00
|
|
|
};
|
2015-03-02 00:09:33 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
// A clients transaction in the mixing pool
|
2014-12-09 02:17:57 +01:00
|
|
|
class CDarkSendEntry
|
|
|
|
{
|
|
|
|
public:
|
2016-08-05 21:49:45 +02:00
|
|
|
std::vector<CTxDSIn> vecTxDSIn;
|
|
|
|
std::vector<CTxDSOut> vecTxDSOut;
|
|
|
|
CTransaction txCollateral;
|
2016-08-29 21:14:34 +02:00
|
|
|
CAmount nAmount; // depreciated since 12.1, it's used for backwards compatibility only and can be removed with future protocol bump
|
2016-08-05 21:49:45 +02:00
|
|
|
int64_t nTimeAdded; // time in UTC milliseconds
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
CDarkSendEntry() :
|
2016-08-29 21:14:34 +02:00
|
|
|
vecTxDSIn(std::vector<CTxDSIn>()),
|
|
|
|
vecTxDSOut(std::vector<CTxDSOut>()),
|
2016-08-05 21:49:45 +02:00
|
|
|
txCollateral(CTransaction()),
|
|
|
|
nAmount(0),
|
2016-08-29 21:14:34 +02:00
|
|
|
nTimeAdded(0)
|
2016-08-12 07:43:18 +02:00
|
|
|
{}
|
2015-03-06 23:17:51 +01:00
|
|
|
|
2016-08-29 21:14:34 +02:00
|
|
|
CDarkSendEntry(const std::vector<CTxIn>& vecTxIn, const std::vector<CTxOut>& vecTxOut, const CTransaction& txCollateral) :
|
|
|
|
txCollateral(txCollateral),
|
|
|
|
nAmount(0),
|
|
|
|
nTimeAdded(GetTime())
|
|
|
|
{
|
|
|
|
BOOST_FOREACH(CTxIn txin, vecTxIn)
|
|
|
|
vecTxDSIn.push_back(txin);
|
|
|
|
BOOST_FOREACH(CTxOut txout, vecTxOut)
|
|
|
|
vecTxDSOut.push_back(txout);
|
|
|
|
}
|
|
|
|
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
|
|
|
READWRITE(vecTxDSIn);
|
|
|
|
READWRITE(nAmount);
|
|
|
|
READWRITE(txCollateral);
|
|
|
|
READWRITE(vecTxDSOut);
|
|
|
|
}
|
2015-03-06 23:17:51 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
bool AddScriptSig(const CTxIn& txin);
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-09-01 09:03:47 +02:00
|
|
|
bool IsExpired() { return GetTime() - nTimeAdded > PRIVATESEND_QUEUE_TIMEOUT; }
|
2014-12-09 02:17:57 +01:00
|
|
|
};
|
|
|
|
|
2015-03-02 00:09:33 +01:00
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/**
|
2016-08-05 21:49:45 +02:00
|
|
|
* A currently inprogress mixing merge and denomination information
|
2015-03-05 08:49:50 +01:00
|
|
|
*/
|
2014-12-09 02:17:57 +01:00
|
|
|
class CDarksendQueue
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
int nDenom;
|
2016-08-05 21:49:45 +02:00
|
|
|
CTxIn vin;
|
|
|
|
int64_t nTime;
|
|
|
|
bool fReady; //ready for submit
|
2014-12-09 02:17:57 +01:00
|
|
|
std::vector<unsigned char> vchSig;
|
|
|
|
|
2016-08-12 07:43:18 +02:00
|
|
|
CDarksendQueue() :
|
|
|
|
nDenom(0),
|
|
|
|
vin(CTxIn()),
|
|
|
|
nTime(0),
|
|
|
|
fReady(false),
|
|
|
|
vchSig(std::vector<unsigned char>())
|
|
|
|
{}
|
2016-08-05 21:49:45 +02:00
|
|
|
|
|
|
|
CDarksendQueue(int nDenom, CTxIn vin, int64_t nTime, bool fReady) :
|
|
|
|
nDenom(nDenom),
|
|
|
|
vin(vin),
|
|
|
|
nTime(nTime),
|
2016-08-12 07:43:18 +02:00
|
|
|
fReady(fReady),
|
|
|
|
vchSig(std::vector<unsigned char>())
|
|
|
|
{}
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2015-04-03 00:51:08 +02:00
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
2014-12-09 02:17:57 +01:00
|
|
|
READWRITE(nDenom);
|
|
|
|
READWRITE(vin);
|
2016-08-05 21:49:45 +02:00
|
|
|
READWRITE(nTime);
|
|
|
|
READWRITE(fReady);
|
2014-12-09 02:17:57 +01:00
|
|
|
READWRITE(vchSig);
|
2015-04-03 00:51:08 +02:00
|
|
|
}
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
bool GetAddress(CService &addrRet);
|
|
|
|
bool GetProtocolVersion(int &nProtocolVersionRet);
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
/** Sign this mixing transaction
|
2015-03-05 08:49:50 +01:00
|
|
|
* \return true if all conditions are met:
|
2015-03-05 09:10:15 +01:00
|
|
|
* 1) we have an active Masternode,
|
|
|
|
* 2) we have a valid Masternode private key,
|
2015-03-05 08:49:50 +01:00
|
|
|
* 3) we signed the message successfully, and
|
|
|
|
* 4) we verified the message successfully
|
|
|
|
*/
|
2014-12-09 02:17:57 +01:00
|
|
|
bool Sign();
|
2015-03-05 09:10:15 +01:00
|
|
|
/// Check if we have a valid Masternode address
|
2014-12-09 02:17:57 +01:00
|
|
|
bool CheckSignature();
|
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
bool Relay();
|
|
|
|
|
|
|
|
/// Is this queue expired?
|
2016-09-01 09:03:47 +02:00
|
|
|
bool IsExpired() { return GetTime() - nTime > PRIVATESEND_QUEUE_TIMEOUT; }
|
2016-08-29 21:17:00 +02:00
|
|
|
|
|
|
|
std::string ToString()
|
|
|
|
{
|
|
|
|
return strprintf("nDenom=%d, nTime=%lld, fReady=%s, masternode=%s",
|
|
|
|
nDenom, nTime, fReady ? "true" : "false", vin.prevout.ToStringShort());
|
|
|
|
}
|
2014-12-09 02:17:57 +01:00
|
|
|
};
|
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
/** Helper class to store mixing transaction (tx) information.
|
2015-03-05 08:49:50 +01:00
|
|
|
*/
|
2014-12-09 02:17:57 +01:00
|
|
|
class CDarksendBroadcastTx
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CTransaction tx;
|
|
|
|
CTxIn vin;
|
2016-08-05 21:49:45 +02:00
|
|
|
std::vector<unsigned char> vchSig;
|
2014-12-09 02:17:57 +01:00
|
|
|
int64_t sigTime;
|
2016-08-05 21:49:45 +02:00
|
|
|
|
2016-08-12 07:43:18 +02:00
|
|
|
CDarksendBroadcastTx() :
|
|
|
|
tx(CTransaction()),
|
|
|
|
vin(CTxIn()),
|
|
|
|
vchSig(std::vector<unsigned char>()),
|
|
|
|
sigTime(0)
|
|
|
|
{}
|
2016-08-05 21:49:45 +02:00
|
|
|
|
|
|
|
CDarksendBroadcastTx(CTransaction tx, CTxIn vin, int64_t sigTime) :
|
2016-08-12 07:43:18 +02:00
|
|
|
tx(tx),
|
|
|
|
vin(vin),
|
|
|
|
vchSig(std::vector<unsigned char>()),
|
|
|
|
sigTime(sigTime)
|
|
|
|
{}
|
2016-08-05 21:49:45 +02:00
|
|
|
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
|
|
|
READWRITE(tx);
|
|
|
|
READWRITE(vin);
|
|
|
|
READWRITE(vchSig);
|
|
|
|
READWRITE(sigTime);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Sign();
|
|
|
|
bool CheckSignature();
|
2014-12-09 02:17:57 +01:00
|
|
|
};
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/** Helper object for signing and checking signatures
|
|
|
|
*/
|
2014-12-09 02:17:57 +01:00
|
|
|
class CDarkSendSigner
|
|
|
|
{
|
|
|
|
public:
|
2016-08-12 07:43:18 +02:00
|
|
|
/// Is the input associated with this public key? (and there is 1000 DASH - checking if valid masternode)
|
2016-08-05 21:49:45 +02:00
|
|
|
bool IsVinAssociatedWithPubkey(const CTxIn& vin, const CPubKey& pubkey);
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Set the private/public key values, returns true if successful
|
2016-08-19 13:50:04 +02:00
|
|
|
bool GetKeysFromSecret(std::string strSecret, CKey& keyRet, CPubKey& pubkeyRet);
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Sign the message, returns true if successful
|
2016-08-19 13:50:04 +02:00
|
|
|
bool SignMessage(std::string strMessage, std::vector<unsigned char>& vchSigRet, CKey key);
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Verify the message, returns true if succcessful
|
2016-08-12 07:43:18 +02:00
|
|
|
bool VerifyMessage(CPubKey pubkey, const std::vector<unsigned char>& vchSig, std::string strMessage, std::string& strErrorRet);
|
2014-12-09 02:17:57 +01:00
|
|
|
};
|
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
/** Used to keep track of current status of mixing pool
|
2015-03-05 08:49:50 +01:00
|
|
|
*/
|
2015-03-02 00:09:33 +01:00
|
|
|
class CDarksendPool
|
2014-12-09 02:17:57 +01:00
|
|
|
{
|
2015-07-14 07:25:07 +02:00
|
|
|
private:
|
2015-04-15 00:40:28 +02:00
|
|
|
enum messages {
|
|
|
|
ERR_ALREADY_HAVE,
|
|
|
|
ERR_DENOM,
|
|
|
|
ERR_ENTRIES_FULL,
|
|
|
|
ERR_EXISTING_TX,
|
|
|
|
ERR_FEES,
|
|
|
|
ERR_INVALID_COLLATERAL,
|
|
|
|
ERR_INVALID_INPUT,
|
|
|
|
ERR_INVALID_SCRIPT,
|
|
|
|
ERR_INVALID_TX,
|
|
|
|
ERR_MAXIMUM,
|
|
|
|
ERR_MN_LIST,
|
|
|
|
ERR_MODE,
|
|
|
|
ERR_NON_STANDARD_PUBKEY,
|
|
|
|
ERR_NOT_A_MN,
|
|
|
|
ERR_QUEUE_FULL,
|
|
|
|
ERR_RECENT,
|
|
|
|
ERR_SESSION,
|
|
|
|
ERR_MISSING_TX,
|
|
|
|
ERR_VERSION,
|
|
|
|
MSG_NOERR,
|
2015-06-24 18:23:22 +02:00
|
|
|
MSG_SUCCESS,
|
|
|
|
MSG_ENTRIES_ADDED
|
2015-04-15 00:40:28 +02:00
|
|
|
};
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
mutable CCriticalSection cs_darksend;
|
2014-12-28 00:45:07 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
// The current mixing sessions in progress on the network
|
|
|
|
std::vector<CDarksendQueue> vecDarksendQueue;
|
|
|
|
// Keep track of the used Masternodes
|
|
|
|
std::vector<CTxIn> vecMasternodesUsed;
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
std::vector<CAmount> vecDenominationsSkipped;
|
|
|
|
std::vector<COutPoint> vecOutPointLocked;
|
|
|
|
// Mixing uses collateral transactions to trust parties entering the pool
|
|
|
|
// to behave honestly. If they don't it takes their money.
|
|
|
|
std::vector<CTransaction> vecSessionCollateral;
|
|
|
|
std::vector<CDarkSendEntry> vecEntries; // Masternode/clients entries
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
unsigned int nState; // should be one of the POOL_STATE_XXX values
|
|
|
|
int64_t nLastTimeChanged; // last time the 'state' changed, in UTC milliseconds
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
int nCachedLastSuccessBlock;
|
|
|
|
int nMinBlockSpacing; //required blocks between mixes
|
|
|
|
const CBlockIndex *pCurrentBlockIndex; // Keep track of current block index
|
2015-02-23 21:07:37 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
int nSessionID;
|
|
|
|
int nSessionUsers; //N Users have said they'll join
|
|
|
|
bool fSessionFoundMasternode; //If we've found a compatible Masternode
|
2015-12-02 23:12:16 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
unsigned int nEntriesCount;
|
|
|
|
bool fLastEntryAccepted;
|
|
|
|
unsigned int nAcceptedEntriesCount;
|
2016-01-24 20:05:31 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
std::string strLastMessage;
|
|
|
|
std::string strAutoDenomResult;
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
bool fUnitTest;
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
CMutableTransaction txMyCollateral; // client side collateral
|
|
|
|
CMutableTransaction finalMutableTransaction; // the finalized transaction ready for signing
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
/// Add a clients entry to the pool
|
2016-08-29 21:14:34 +02:00
|
|
|
bool AddEntry(const CDarkSendEntry& entryNew, int& nErrorIDRet);
|
2016-08-05 21:49:45 +02:00
|
|
|
/// Add signature to a txin
|
|
|
|
bool AddScriptSig(const CTxIn& txin);
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
/// Charge fees to bad actors (Charge clients a fee if they're abusive)
|
|
|
|
void ChargeFees();
|
|
|
|
/// Rarely charge fees to pay miners
|
|
|
|
void ChargeRandomFees();
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
/// Check for process
|
|
|
|
void CheckPool();
|
2015-06-24 18:08:14 +02:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
void CheckFinalTransaction();
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
void CompletedTransaction(bool fError, int nErrorID);
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
/// Get the denominations for a specific amount of dash.
|
|
|
|
int GetDenominationsByAmounts(const std::vector<CAmount>& vecAmount);
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
std::string GetMessageByID(int nMessageID);
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Get the maximum number of transactions for the pool
|
2016-08-05 21:49:45 +02:00
|
|
|
int GetMaxPoolTransactions() { return Params().PoolMaxTransactions(); }
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Are these outputs compatible with other client in the pool?
|
2016-08-29 21:14:34 +02:00
|
|
|
bool IsOutputsCompatibleWithSessionDenom(const std::vector<CTxDSOut>& vecTxDSOut);
|
2016-08-05 21:49:45 +02:00
|
|
|
/// Is this nDenom compatible with other client in the pool?
|
|
|
|
bool IsDenomCompatibleWithSession(int nDenom, CTransaction txCollateral, int &nErrorID);
|
2015-03-02 00:09:33 +01:00
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// If the collateral is valid given by a client
|
2014-12-09 02:17:57 +01:00
|
|
|
bool IsCollateralValid(const CTransaction& txCollateral);
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Check that all inputs are signed. (Are all inputs signed?)
|
2016-08-05 21:49:45 +02:00
|
|
|
bool IsSignaturesComplete();
|
2016-09-21 16:03:04 +02:00
|
|
|
/// Check to make sure a given input matches an input in the pool and its scriptSig is valid
|
|
|
|
bool IsInputScriptSigValid(const CTxIn& txin);
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
bool IsDenomSkipped(CAmount nDenomValue) {
|
|
|
|
return std::find(vecDenominationsSkipped.begin(), vecDenominationsSkipped.end(), nDenomValue) != vecDenominationsSkipped.end();
|
|
|
|
}
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
bool IsNull() const { return nState == POOL_STATE_ACCEPTING_ENTRIES && vecEntries.empty(); }
|
2015-03-18 18:19:13 +01:00
|
|
|
|
2016-07-15 12:21:20 +02:00
|
|
|
/// Create denominations
|
|
|
|
bool CreateDenominated();
|
|
|
|
bool CreateDenominated(const CompactTallyItem& tallyItem);
|
2016-09-02 14:19:29 +02:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
/// Split up large inputs or make fee sized inputs
|
|
|
|
bool MakeCollateralAmounts();
|
|
|
|
bool MakeCollateralAmounts(const CompactTallyItem& tallyItem);
|
|
|
|
|
2016-09-02 14:19:29 +02:00
|
|
|
/// As a client, submit part of a future mixing transaction to a Masternode to start the process
|
|
|
|
bool SubmitDenominate();
|
|
|
|
/// step 1: prepare denominated inputs and outputs
|
|
|
|
bool PrepareDenominate(int nMinRounds, int nMaxRounds, std::string& strErrorRet, std::vector<CTxIn>& vecTxInRet, std::vector<CTxOut>& vecTxOutRet);
|
|
|
|
/// step 2: send denominated inputs and outputs prepared in step 1
|
|
|
|
bool SendDenominate(const std::vector<CTxIn>& vecTxIn, const std::vector<CTxOut>& vecTxOut);
|
2016-08-05 21:49:45 +02:00
|
|
|
|
|
|
|
/// Get Masternode updates about the progress of mixing
|
|
|
|
bool UpdatePoolStateOnClient(int nStateNew, int nEntriesCountNew, int nAcceptedEntriesCountNew, int &nErrorID, int nSessionIDNew=0);
|
|
|
|
// Set the 'state' value, with some logging and capturing when the state changed
|
|
|
|
void SetState(unsigned int nStateNew);
|
|
|
|
|
|
|
|
/// As a client, check and sign the final transaction
|
|
|
|
bool SignFinalTransaction(const CTransaction& finalTransactionNew, CNode* node);
|
|
|
|
|
|
|
|
/// Relay mixing Messages
|
|
|
|
void RelayFinalTransaction(const CTransaction& txFinal);
|
|
|
|
void RelaySignaturesAnon(std::vector<CTxIn>& vin);
|
|
|
|
void RelayInAnon(std::vector<CTxIn>& vin, std::vector<CTxOut>& vout);
|
2016-08-29 21:14:34 +02:00
|
|
|
void RelayIn(const CDarkSendEntry& entry);
|
2016-08-05 21:49:45 +02:00
|
|
|
void RelayStatus(int nErrorID=MSG_NOERR);
|
|
|
|
void RelayCompletedTransaction(bool fError, int nErrorID);
|
|
|
|
|
|
|
|
public:
|
|
|
|
CMasternode* pSubmittedToMasternode;
|
|
|
|
int nSessionDenom; //Users must submit an denom matching this
|
|
|
|
int nCachedNumBlocks; //used for the overview screen
|
|
|
|
bool fCreateAutoBackups; //builtin support for automatic backups
|
|
|
|
|
|
|
|
CDarksendPool() :
|
|
|
|
nCachedLastSuccessBlock(0),
|
|
|
|
nMinBlockSpacing(0),
|
|
|
|
fUnitTest(false),
|
|
|
|
txMyCollateral(CMutableTransaction()),
|
|
|
|
nCachedNumBlocks(std::numeric_limits<int>::max()),
|
|
|
|
fCreateAutoBackups(true) { SetNull(); }
|
|
|
|
|
|
|
|
/** Process a mixing message using the protocol below
|
|
|
|
* \param pfrom
|
|
|
|
* \param strCommand lower case command string; valid values are:
|
|
|
|
* Command | Description
|
|
|
|
* -------- | -----------------
|
|
|
|
* dsa | Acceptable
|
|
|
|
* dsc | Complete
|
|
|
|
* dsf | Final tx
|
|
|
|
* dsi | Vector of CTxIn
|
|
|
|
* dsq | Queue
|
|
|
|
* dss | Signal Final Tx
|
|
|
|
* dssu | status update
|
|
|
|
* \param vRecv
|
|
|
|
*/
|
|
|
|
void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
2016-07-15 12:21:20 +02:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
void InitDenominations();
|
|
|
|
void ClearSkippedDenominations() { vecDenominationsSkipped.clear(); }
|
2015-03-18 18:19:13 +01:00
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Get the denominations for a list of outputs (returns a bitshifted integer)
|
2016-08-05 21:49:45 +02:00
|
|
|
int GetDenominations(const std::vector<CTxOut>& vecTxOut, bool fSingleRandomDenom = false);
|
|
|
|
int GetDenominations(const std::vector<CTxDSOut>& vecTxDSOut);
|
|
|
|
std::string GetDenominationsToString(int nDenom);
|
2015-03-06 23:17:51 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
void SetMinBlockSpacing(int nMinBlockSpacingIn) { nMinBlockSpacing = nMinBlockSpacingIn; }
|
2015-03-02 00:09:33 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
void ResetPool();
|
|
|
|
void SetNull();
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
void UnlockCoins();
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
int GetQueueSize() const { return vecDarksendQueue.size(); }
|
|
|
|
int GetState() const { return nState; }
|
|
|
|
std::string GetStatus();
|
2015-03-02 00:09:33 +01:00
|
|
|
|
2016-08-05 21:49:45 +02:00
|
|
|
int GetEntriesCount() const { return vecEntries.size(); }
|
|
|
|
/// Get the count of the accepted entries
|
|
|
|
int GetCountEntriesAccepted() const { return nAcceptedEntriesCount; }
|
|
|
|
|
|
|
|
/// Passively run mixing in the background according to the configuration in settings
|
|
|
|
bool DoAutomaticDenominating(bool fDryRun=false);
|
|
|
|
|
|
|
|
void CheckTimeout();
|
|
|
|
void CheckForCompleteQueue();
|
|
|
|
/// Do we have enough users to take entries?
|
|
|
|
bool IsSessionReady(){ return nSessionUsers >= GetMaxPoolTransactions(); }
|
|
|
|
|
|
|
|
|
|
|
|
/// Process a new block
|
|
|
|
void NewBlock();
|
2016-03-02 22:20:04 +01:00
|
|
|
|
|
|
|
void UpdatedBlockTip(const CBlockIndex *pindex);
|
2015-03-02 00:09:33 +01:00
|
|
|
};
|
2014-12-09 02:17:57 +01:00
|
|
|
|
|
|
|
void ThreadCheckDarkSendPool();
|
|
|
|
|
|
|
|
#endif
|