neobytes/src/privatesend.h

362 lines
9.8 KiB
C
Raw Normal View History

2016-12-20 14:26:45 +01:00
// Copyright (c) 2014-2017 The Dash Core developers
// 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
#ifndef PRIVATESEND_H
#define PRIVATESEND_H
#include "chainparams.h"
#include "primitives/transaction.h"
#include "pubkey.h"
#include "sync.h"
#include "tinyformat.h"
#include "timedata.h"
class CPrivateSend;
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
class CConnman;
// timeouts
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-09-30 20:19:26 +02:00
//! minimum peer version accepted by mixing pool
static const int MIN_PRIVATESEND_PEER_PROTO_VERSION = 70208;
static const CAmount PRIVATESEND_ENTRY_MAX_SIZE = 9;
// pool responses
enum PoolMessage {
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, // not used
ERR_QUEUE_FULL,
ERR_RECENT,
ERR_SESSION,
ERR_MISSING_TX,
ERR_VERSION,
MSG_NOERR,
MSG_SUCCESS,
MSG_ENTRIES_ADDED,
MSG_POOL_MIN = ERR_ALREADY_HAVE,
MSG_POOL_MAX = MSG_ENTRIES_ADDED
};
2015-04-03 00:51:08 +02:00
// pool states
enum PoolState {
POOL_STATE_IDLE,
POOL_STATE_QUEUE,
POOL_STATE_ACCEPTING_ENTRIES,
POOL_STATE_SIGNING,
POOL_STATE_ERROR,
POOL_STATE_SUCCESS,
POOL_STATE_MIN = POOL_STATE_IDLE,
POOL_STATE_MAX = POOL_STATE_SUCCESS
};
// status update message constants
enum PoolStatusUpdate {
STATUS_REJECTED,
STATUS_ACCEPTED
};
/** Holds an mixing input
2015-03-05 08:49:50 +01:00
*/
2015-03-02 00:09:33 +01:00
class CTxDSIn : public CTxIn
{
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
CTxDSIn(const CTxIn& txin) :
CTxIn(txin),
fHasSig(false),
nSentTimes(0)
{}
CTxDSIn() :
CTxIn(),
fHasSig(false),
nSentTimes(0)
{}
};
/** Holds an mixing output
*/
class CTxDSOut : public CTxOut
{
public:
2015-03-18 18:19:13 +01:00
int nSentTimes; //times we've sent this anonymously
CTxDSOut(const CTxOut& out) :
CTxOut(out),
nSentTimes(0)
{}
CTxDSOut() :
CTxOut(),
nSentTimes(0)
{}
};
2015-03-02 00:09:33 +01:00
// A clients transaction in the mixing pool
class CDarkSendEntry
{
public:
std::vector<CTxDSIn> vecTxDSIn;
std::vector<CTxDSOut> vecTxDSOut;
CTransaction txCollateral;
// memory only
CService addr;
CDarkSendEntry() :
vecTxDSIn(std::vector<CTxDSIn>()),
vecTxDSOut(std::vector<CTxDSOut>()),
txCollateral(CTransaction()),
addr(CService())
{}
CDarkSendEntry(const std::vector<CTxIn>& vecTxIn, const std::vector<CTxOut>& vecTxOut, const CTransaction& txCollateral);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(vecTxDSIn);
READWRITE(txCollateral);
READWRITE(vecTxDSOut);
}
bool AddScriptSig(const CTxIn& txin);
};
2015-03-02 00:09:33 +01:00
2015-03-05 08:49:50 +01:00
/**
* A currently inprogress mixing merge and denomination information
2015-03-05 08:49:50 +01:00
*/
class CDarksendQueue
{
public:
int nDenom;
CTxIn vin;
int64_t nTime;
bool fReady; //ready for submit
std::vector<unsigned char> vchSig;
// memory only
bool fTried;
CDarksendQueue() :
nDenom(0),
vin(CTxIn()),
nTime(0),
fReady(false),
vchSig(std::vector<unsigned char>()),
fTried(false)
{}
CDarksendQueue(int nDenom, COutPoint outpoint, int64_t nTime, bool fReady) :
nDenom(nDenom),
vin(CTxIn(outpoint)),
nTime(nTime),
fReady(fReady),
vchSig(std::vector<unsigned char>()),
fTried(false)
{}
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) {
READWRITE(nDenom);
READWRITE(vin);
READWRITE(nTime);
READWRITE(fReady);
READWRITE(vchSig);
2015-04-03 00:51:08 +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
*/
bool Sign();
2015-03-05 09:10:15 +01:00
/// Check if we have a valid Masternode address
bool CheckSignature(const CPubKey& pubKeyMasternode);
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
bool Relay(CConnman &connman);
/// Is this queue expired?
bool IsExpired() { return GetAdjustedTime() - nTime > PRIVATESEND_QUEUE_TIMEOUT; }
std::string ToString()
{
return strprintf("nDenom=%d, nTime=%lld, fReady=%s, fTried=%s, masternode=%s",
nDenom, nTime, fReady ? "true" : "false", fTried ? "true" : "false", vin.prevout.ToStringShort());
}
friend bool operator==(const CDarksendQueue& a, const CDarksendQueue& b)
{
return a.nDenom == b.nDenom && a.vin.prevout == b.vin.prevout && a.nTime == b.nTime && a.fReady == b.fReady;
}
};
/** Helper class to store mixing transaction (tx) information.
2015-03-05 08:49:50 +01:00
*/
class CDarksendBroadcastTx
{
private:
// memory only
// when corresponding tx is 0-confirmed or conflicted, nConfirmedHeight is -1
int nConfirmedHeight;
public:
CTransaction tx;
CTxIn vin;
std::vector<unsigned char> vchSig;
int64_t sigTime;
CDarksendBroadcastTx() :
nConfirmedHeight(-1),
tx(),
vin(),
vchSig(),
sigTime(0)
{}
CDarksendBroadcastTx(CTransaction tx, COutPoint outpoint, int64_t sigTime) :
nConfirmedHeight(-1),
tx(tx),
vin(CTxIn(outpoint)),
vchSig(),
sigTime(sigTime)
{}
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);
}
friend bool operator==(const CDarksendBroadcastTx& a, const CDarksendBroadcastTx& b)
{
return a.tx == b.tx;
}
friend bool operator!=(const CDarksendBroadcastTx& a, const CDarksendBroadcastTx& b)
{
return !(a == b);
}
explicit operator bool() const
{
return *this != CDarksendBroadcastTx();
}
bool Sign();
bool CheckSignature(const CPubKey& pubKeyMasternode);
void SetConfirmedHeight(int nConfirmedHeightIn) { nConfirmedHeight = nConfirmedHeightIn; }
bool IsExpired(int nHeight);
};
// base class
class CPrivateSendBase
{
protected:
// The current mixing sessions in progress on the network
std::vector<CDarksendQueue> vecDarksendQueue;
std::vector<CDarkSendEntry> vecEntries; // Masternode/clients entries
2016-10-20 23:11:57 +02:00
PoolState nState; // should be one of the POOL_STATE_XXX values
int64_t nTimeLastSuccessfulStep; // the time when last successful mixing step was performed, in UTC milliseconds
int nSessionID; // 0 if no mixing session is active
CMutableTransaction finalMutableTransaction; // the finalized transaction ready for signing
void SetNull();
public:
int nSessionDenom; //Users must submit an denom matching this
CPrivateSendBase() { SetNull(); }
int GetQueueSize() const { return vecDarksendQueue.size(); }
int GetState() const { return nState; }
std::string GetStateString() const;
int GetEntriesCount() const { return vecEntries.size(); }
};
// helper class
class CPrivateSend
{
private:
// make constructor, destructor and copying not available
CPrivateSend() {}
~CPrivateSend() {}
CPrivateSend(CPrivateSend const&) = delete;
CPrivateSend& operator= (CPrivateSend const&) = delete;
static const CAmount COLLATERAL = 0.001 * COIN;
// static members
static std::vector<CAmount> vecStandardDenominations;
static std::map<uint256, CDarksendBroadcastTx> mapDSTX;
static CCriticalSection cs_mapdstx;
public:
static void InitStandardDenominations();
static std::vector<CAmount> GetStandardDenominations() { return vecStandardDenominations; }
static CAmount GetSmallestDenomination() { return vecStandardDenominations.back(); }
/// Get the denominations for a specific amount of dash.
static int GetDenominationsByAmounts(const std::vector<CAmount>& vecAmount);
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)
static int GetDenominations(const std::vector<CTxOut>& vecTxOut, bool fSingleRandomDenom = false);
static int GetDenominations(const std::vector<CTxDSOut>& vecTxDSOut);
static std::string GetDenominationsToString(int nDenom);
static bool GetDenominationsBits(int nDenom, std::vector<int> &vecBitsRet);
static std::string GetMessageByID(PoolMessage nMessageID);
/// Get the maximum number of transactions for the pool
static int GetMaxPoolTransactions() { return Params().PoolMaxTransactions(); }
2015-03-02 00:09:33 +01:00
static CAmount GetMaxPoolAmount() { return vecStandardDenominations.empty() ? 0 : PRIVATESEND_ENTRY_MAX_SIZE * vecStandardDenominations.front(); }
/// If the collateral is valid given by a client
static bool IsCollateralValid(const CTransaction& txCollateral);
static CAmount GetCollateralAmount() { return COLLATERAL; }
static CAmount GetMaxCollateralAmount() { return COLLATERAL*4; }
static void AddDSTX(const CDarksendBroadcastTx& dstx);
static CDarksendBroadcastTx GetDSTX(const uint256& hash);
static void CheckDSTXes(int nHeight);
static void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
2015-03-02 00:09:33 +01:00
};
Eliminate remaining uses of g_connman in Dash-specific code. (#1635) This monstrous change eliminates all remaining uses of g_connman global variable in Dash-specific code. Unlike previous changes eliminating g_connman use that were isolated to particular modules, this one covers multiple modules simultaneously because they are so interdependent that change in one module was quickly spreading to others. This is mostly invariant change that was done by * changing all functions using g_connman to use connman argument, * changing all functions calling these functions to use connman argument, * repeating previous step until there's nothing to change. After multiple iterations, this process converged to final result, producing code that is mostly equivalent to original one, but passing CConnman instance through arguments instead of global variable. The only exception to equivalence of resulting code is that I had to create overload of CMasternodeMan::CheckAndRemove() method without arguments that does nothing just for use in CFlatDB<CMasternodeMan>::Dump() and CFlatDB<CMasternodeMan>::Load() methods. Normal CMasternodeMan::CheckAndRemove() overload now has argument of CConnman& type and is used everywhere else. The normal overload has this code in the beginning: if(!masternodeSync.IsMasternodeListSynced()) return; Masternode list is not synced yet when we load "mncache.dat" file, and we save "mncache.dat" file on shutdown, so I presume that it's OK to use overload that does nothing in both cases. Signed-off-by: Oleg Girko <ol@infoserver.lv>
2017-09-19 16:51:38 +02:00
void ThreadCheckPrivateSend(CConnman& connman);
#endif