2015-03-18 00:06:58 +01:00
|
|
|
// Copyright (c) 2014-2015 The Dash 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
|
|
|
|
|
|
|
|
#include "core.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "activemasternode.h"
|
2015-02-23 21:01:21 +01:00
|
|
|
#include "masternodeman.h"
|
2015-03-02 00:09:33 +01:00
|
|
|
#include "darksend-relay.h"
|
2014-12-09 02:17:57 +01:00
|
|
|
|
|
|
|
class CTxIn;
|
2015-03-02 00:09:33 +01:00
|
|
|
class CDarksendPool;
|
2014-12-09 02:17:57 +01:00
|
|
|
class CDarkSendSigner;
|
|
|
|
class CMasterNodeVote;
|
|
|
|
class CBitcoinAddress;
|
|
|
|
class CDarksendQueue;
|
|
|
|
class CDarksendBroadcastTx;
|
|
|
|
class CActiveMasternode;
|
|
|
|
|
2015-03-02 00:09:33 +01:00
|
|
|
// pool states for mixing
|
2014-12-09 02:17:57 +01:00
|
|
|
#define POOL_MAX_TRANSACTIONS 3 // wait for X transactions to merge and publish
|
2015-03-02 00:09:33 +01:00
|
|
|
#define POOL_MAX_TRANSACTIONS_TESTNET 2 // wait for X transactions to merge and publish
|
2014-12-09 02:17:57 +01:00
|
|
|
#define POOL_STATUS_UNKNOWN 0 // waiting for update
|
|
|
|
#define POOL_STATUS_IDLE 1 // waiting for update
|
|
|
|
#define POOL_STATUS_QUEUE 2 // waiting in a queue
|
|
|
|
#define POOL_STATUS_ACCEPTING_ENTRIES 3 // accepting entries
|
|
|
|
#define POOL_STATUS_FINALIZE_TRANSACTION 4 // master node will broadcast what it accepted
|
|
|
|
#define POOL_STATUS_SIGNING 5 // check inputs/outputs, sign final tx
|
|
|
|
#define POOL_STATUS_TRANSMISSION 6 // transmit transaction
|
|
|
|
#define POOL_STATUS_ERROR 7 // error
|
|
|
|
#define POOL_STATUS_SUCCESS 8 // success
|
|
|
|
|
|
|
|
// status update message constants
|
|
|
|
#define MASTERNODE_ACCEPTED 1
|
|
|
|
#define MASTERNODE_REJECTED 0
|
|
|
|
#define MASTERNODE_RESET -1
|
|
|
|
|
2015-03-18 18:19:13 +01:00
|
|
|
#define DARKSEND_QUEUE_TIMEOUT 180 // in seconds
|
2015-03-05 08:49:50 +01:00
|
|
|
#define DARKSEND_SIGNING_TIMEOUT 30 // in seconds
|
2015-03-18 18:19:13 +01:00
|
|
|
#define DARKSEND_DOWNGRADE_TIMEOUT 60 // in seconds
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2015-03-02 00:09:33 +01:00
|
|
|
// used for anonymous relaying of inputs/outputs/sigs
|
|
|
|
#define DARKSEND_RELAY_IN 1
|
|
|
|
#define DARKSEND_RELAY_OUT 2
|
|
|
|
#define DARKSEND_RELAY_SIG 3
|
2015-02-26 18:09:39 +01:00
|
|
|
|
2015-03-02 00:09:33 +01:00
|
|
|
extern CDarksendPool darkSendPool;
|
2014-12-09 02:17:57 +01:00
|
|
|
extern CDarkSendSigner darkSendSigner;
|
|
|
|
extern std::vector<CDarksendQueue> vecDarksendQueue;
|
|
|
|
extern std::string strMasterNodePrivKey;
|
|
|
|
extern map<uint256, CDarksendBroadcastTx> mapDarksendBroadcastTxes;
|
|
|
|
extern CActiveMasternode activeMasternode;
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
// get the Darksend chain depth for a given input
|
2014-12-09 02:17:57 +01:00
|
|
|
int GetInputDarksendRounds(CTxIn in, int rounds=0);
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/** Holds an Darksend input
|
|
|
|
*/
|
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
|
|
|
|
2015-03-02 00:09:33 +01:00
|
|
|
CTxDSIn(const CTxIn& in)
|
2014-12-09 02:17:57 +01:00
|
|
|
{
|
2015-03-02 00:09:33 +01:00
|
|
|
prevout = in.prevout;
|
|
|
|
scriptSig = in.scriptSig;
|
|
|
|
prevPubKey = in.prevPubKey;
|
|
|
|
nSequence = in.nSequence;
|
2015-03-06 23:17:51 +01:00
|
|
|
nSentTimes = 0;
|
2014-12-09 02:17:57 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-03-06 23:17:51 +01:00
|
|
|
/** Holds an Darksend output
|
|
|
|
*/
|
|
|
|
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
|
|
|
|
|
|
|
CTxDSOut(const CTxOut& out)
|
|
|
|
{
|
|
|
|
nValue = out.nValue;
|
|
|
|
nRounds = out.nRounds;
|
|
|
|
scriptPubKey = out.scriptPubKey;
|
|
|
|
nSentTimes = 0;
|
|
|
|
}
|
|
|
|
};
|
2015-03-02 00:09:33 +01:00
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/** A clients transaction in the Darksend pool
|
|
|
|
* -- holds the input/output mapping for each user in the pool
|
|
|
|
*/
|
2014-12-09 02:17:57 +01:00
|
|
|
class CDarkSendEntry
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
bool isSet;
|
2015-03-06 23:17:51 +01:00
|
|
|
std::vector<CTxDSIn> sev;
|
|
|
|
std::vector<CTxDSOut> vout;
|
2014-12-09 02:17:57 +01:00
|
|
|
int64_t amount;
|
|
|
|
CTransaction collateral;
|
|
|
|
CTransaction txSupporting;
|
2015-03-06 08:24:34 +01:00
|
|
|
int64_t addedTime; // time in UTC milliseconds
|
2014-12-09 02:17:57 +01:00
|
|
|
|
|
|
|
CDarkSendEntry()
|
|
|
|
{
|
|
|
|
isSet = false;
|
|
|
|
collateral = CTransaction();
|
|
|
|
amount = 0;
|
|
|
|
}
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Add entries to use for Darksend
|
2014-12-09 02:17:57 +01:00
|
|
|
bool Add(const std::vector<CTxIn> vinIn, int64_t amountIn, const CTransaction collateralIn, const std::vector<CTxOut> voutIn)
|
|
|
|
{
|
|
|
|
if(isSet){return false;}
|
|
|
|
|
2015-03-06 23:17:51 +01:00
|
|
|
BOOST_FOREACH(const CTxIn& in, vinIn)
|
|
|
|
sev.push_back(in);
|
|
|
|
|
|
|
|
BOOST_FOREACH(const CTxOut& out, voutIn)
|
|
|
|
vout.push_back(out);
|
|
|
|
|
2014-12-09 02:17:57 +01:00
|
|
|
amount = amountIn;
|
|
|
|
collateral = collateralIn;
|
|
|
|
isSet = true;
|
|
|
|
addedTime = GetTime();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Is this Darksend expired?
|
2014-12-09 02:17:57 +01:00
|
|
|
bool IsExpired()
|
|
|
|
{
|
|
|
|
return (GetTime() - addedTime) > DARKSEND_QUEUE_TIMEOUT;// 120 seconds
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-03-02 00:09:33 +01:00
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/**
|
|
|
|
* A currently inprogress Darksend merge and denomination information
|
|
|
|
*/
|
2014-12-09 02:17:57 +01:00
|
|
|
class CDarksendQueue
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CTxIn vin;
|
2015-03-06 08:28:25 +01:00
|
|
|
int64_t time;
|
2014-12-09 02:17:57 +01:00
|
|
|
int nDenom;
|
|
|
|
bool ready; //ready for submit
|
|
|
|
std::vector<unsigned char> vchSig;
|
|
|
|
|
2015-03-02 00:09:33 +01:00
|
|
|
//information used for the anonymous relay system
|
|
|
|
int nBlockHeight;
|
|
|
|
std::vector<unsigned char> vchRelaySig;
|
2015-03-06 08:24:34 +01:00
|
|
|
std::string strSharedKey; // shared key
|
2015-03-02 00:09:33 +01:00
|
|
|
|
2014-12-09 02:17:57 +01:00
|
|
|
CDarksendQueue()
|
|
|
|
{
|
|
|
|
nDenom = 0;
|
|
|
|
vin = CTxIn();
|
|
|
|
time = 0;
|
|
|
|
vchSig.clear();
|
2015-03-02 00:09:33 +01:00
|
|
|
vchRelaySig.clear();
|
|
|
|
nBlockHeight = 0;
|
|
|
|
strSharedKey = "";
|
2014-12-09 02:17:57 +01:00
|
|
|
ready = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
IMPLEMENT_SERIALIZE
|
|
|
|
(
|
|
|
|
READWRITE(nDenom);
|
|
|
|
READWRITE(vin);
|
|
|
|
READWRITE(time);
|
|
|
|
READWRITE(ready);
|
|
|
|
READWRITE(vchSig);
|
2015-03-02 00:09:33 +01:00
|
|
|
|
|
|
|
if(ready){
|
|
|
|
READWRITE(vchRelaySig);
|
|
|
|
READWRITE(nBlockHeight);
|
|
|
|
READWRITE(strSharedKey);
|
|
|
|
}
|
2014-12-09 02:17:57 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
bool GetAddress(CService &addr)
|
|
|
|
{
|
2015-02-25 12:54:03 +01:00
|
|
|
CMasternode* pmn = mnodeman.Find(vin);
|
|
|
|
if(pmn != NULL)
|
2015-02-23 21:01:21 +01:00
|
|
|
{
|
2015-02-25 12:54:03 +01:00
|
|
|
addr = pmn->addr;
|
2015-02-23 21:01:21 +01:00
|
|
|
return true;
|
2014-12-09 02:17:57 +01:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Get the protocol version
|
2014-12-09 02:17:57 +01:00
|
|
|
bool GetProtocolVersion(int &protocolVersion)
|
|
|
|
{
|
2015-02-25 12:54:03 +01:00
|
|
|
CMasternode* pmn = mnodeman.Find(vin);
|
|
|
|
if(pmn != NULL)
|
2015-02-23 21:01:21 +01:00
|
|
|
{
|
2015-02-25 12:54:03 +01:00
|
|
|
protocolVersion = pmn->protocolVersion;
|
2015-02-23 21:01:21 +01:00
|
|
|
return true;
|
2014-12-09 02:17:57 +01:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-03-18 18:19:13 +01:00
|
|
|
/// Set the 'strSharedKey'
|
2015-03-05 16:08:03 +01:00
|
|
|
void SetSharedKey(std::string strSharedKey);
|
2015-03-05 16:18:45 +01:00
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/** Sign this Darksend transaction
|
|
|
|
* \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 08:49:50 +01:00
|
|
|
|
2014-12-09 02:17:57 +01:00
|
|
|
bool Relay();
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Is this Darksend expired?
|
2014-12-09 02:17:57 +01:00
|
|
|
bool IsExpired()
|
|
|
|
{
|
|
|
|
return (GetTime() - time) > DARKSEND_QUEUE_TIMEOUT;// 120 seconds
|
|
|
|
}
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/** Helper class to store Darksend transaction (tx) information.
|
|
|
|
*/
|
2014-12-09 02:17:57 +01:00
|
|
|
class CDarksendBroadcastTx
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CTransaction tx;
|
|
|
|
CTxIn vin;
|
|
|
|
vector<unsigned char> vchSig;
|
|
|
|
int64_t sigTime;
|
|
|
|
};
|
|
|
|
|
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:
|
2015-03-18 00:06:58 +01:00
|
|
|
/// Is the inputs associated with this public key? (and there is 1000 DASH - checking if valid masternode)
|
2014-12-09 02:17:57 +01:00
|
|
|
bool IsVinAssociatedWithPubkey(CTxIn& vin, CPubKey& pubkey);
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Set the private/public key values, returns true if successful
|
2014-12-09 02:17:57 +01:00
|
|
|
bool SetKey(std::string strSecret, std::string& errorMessage, CKey& key, CPubKey& pubkey);
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Sign the message, returns true if successful
|
2014-12-09 02:17:57 +01:00
|
|
|
bool SignMessage(std::string strMessage, std::string& errorMessage, std::vector<unsigned char>& vchSig, CKey key);
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Verify the message, returns true if succcessful
|
2014-12-09 02:17:57 +01:00
|
|
|
bool VerifyMessage(CPubKey pubkey, std::vector<unsigned char>& vchSig, std::string strMessage, std::string& errorMessage);
|
|
|
|
};
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/** Build a transaction anonymously
|
|
|
|
*/
|
2015-03-02 00:09:33 +01:00
|
|
|
class CDSAnonTx
|
2014-12-09 02:17:57 +01:00
|
|
|
{
|
2015-03-02 00:09:33 +01:00
|
|
|
public:
|
2015-03-06 08:24:34 +01:00
|
|
|
std::vector<CTxDSIn> vin; // collection of inputs
|
|
|
|
std::vector<CTxOut> vout; // collection of outputs
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Is the transaction valid? (TODO: not defined - remove? or code?)
|
2015-03-02 00:09:33 +01:00
|
|
|
bool IsTransactionValid();
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Add an output
|
2015-03-02 00:09:33 +01:00
|
|
|
bool AddOutput(const CTxOut out);
|
2015-03-18 18:19:13 +01:00
|
|
|
/// Add an input
|
2015-03-02 00:09:33 +01:00
|
|
|
bool AddInput(const CTxIn in);
|
2015-03-18 17:41:30 +01:00
|
|
|
/// Clear Signatures
|
|
|
|
bool ClearSigs();
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Add Signature
|
2015-03-02 00:09:33 +01:00
|
|
|
bool AddSig(const CTxIn in);
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Count the number of entries in the transaction
|
2015-03-02 00:09:33 +01:00
|
|
|
int CountEntries() {return (int)vin.size() + (int)vout.size();}
|
2014-12-09 02:17:57 +01:00
|
|
|
};
|
|
|
|
|
2015-03-06 08:24:34 +01:00
|
|
|
/// TODO: not defined - remove?
|
2015-03-02 00:09:33 +01:00
|
|
|
void ConnectToDarkSendMasterNodeWinner();
|
|
|
|
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/** Used to keep track of current status of Darksend pool
|
|
|
|
*/
|
2015-03-02 00:09:33 +01:00
|
|
|
class CDarksendPool
|
2014-12-09 02:17:57 +01:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2015-03-06 08:24:34 +01:00
|
|
|
std::vector<CDarkSendEntry> myEntries; // clients entries
|
|
|
|
std::vector<CDarkSendEntry> entries; // Masternode entries
|
|
|
|
CTransaction finalTransaction; // the finalized transaction ready for signing
|
|
|
|
CDSAnonTx anonTx; // anonymous inputs/outputs
|
|
|
|
bool fSubmitAnonymousFailed; // initally false, will change to true if when attempts > 5
|
|
|
|
int nCountAttempts; // number of submitted attempts
|
|
|
|
|
|
|
|
int64_t lastTimeChanged; // last time the 'state' changed, in UTC milliseconds
|
|
|
|
int64_t lastAutoDenomination; // TODO; not used - Delete?
|
|
|
|
|
|
|
|
unsigned int state; // should be one of the POOL_STATUS_XXX values
|
2014-12-09 02:17:57 +01:00
|
|
|
unsigned int entriesCount;
|
|
|
|
unsigned int lastEntryAccepted;
|
|
|
|
unsigned int countEntriesAccepted;
|
|
|
|
|
|
|
|
// where collateral should be made out to
|
|
|
|
CScript collateralPubKey;
|
|
|
|
|
|
|
|
std::vector<CTxIn> lockedCoins;
|
|
|
|
|
|
|
|
uint256 masterNodeBlockHash;
|
|
|
|
|
|
|
|
std::string lastMessage;
|
|
|
|
bool completedTransaction;
|
|
|
|
bool unitTest;
|
2015-03-02 00:09:33 +01:00
|
|
|
CMasternode* pSubmittedToMasternode;
|
2014-12-09 02:17:57 +01:00
|
|
|
|
|
|
|
int sessionID;
|
|
|
|
int sessionDenom; //Users must submit an denom matching this
|
|
|
|
int sessionUsers; //N Users have said they'll join
|
2015-03-05 09:10:15 +01:00
|
|
|
bool sessionFoundMasternode; //If we've found a compatible Masternode
|
2014-12-09 02:17:57 +01:00
|
|
|
int64_t sessionTotalValue; //used for autoDenom
|
|
|
|
std::vector<CTransaction> vecSessionCollateral;
|
|
|
|
|
|
|
|
int cachedLastSuccess;
|
|
|
|
int cachedNumBlocks; //used for the overview screen
|
|
|
|
int minBlockSpacing; //required blocks between mixes
|
|
|
|
CTransaction txCollateral;
|
|
|
|
|
2015-01-27 15:46:06 +01:00
|
|
|
int64_t lastNewBlock;
|
|
|
|
|
2014-12-28 00:45:07 +01:00
|
|
|
//debugging data
|
2014-12-28 02:08:45 +01:00
|
|
|
std::string strAutoDenomResult;
|
2014-12-28 00:45:07 +01:00
|
|
|
|
2015-03-02 00:09:33 +01:00
|
|
|
// used for securing the anonymous relay system
|
|
|
|
vector<unsigned char> vchMasternodeRelaySig;
|
|
|
|
int nMasternodeBlockHeight;
|
|
|
|
std::string strMasternodeSharedKey;
|
2015-03-06 23:17:51 +01:00
|
|
|
int nTrickleInputsOutputs;
|
2015-03-02 00:09:33 +01:00
|
|
|
|
|
|
|
CDarksendPool()
|
2014-12-09 02:17:57 +01:00
|
|
|
{
|
2015-03-05 08:49:50 +01:00
|
|
|
/* Darksend uses collateral addresses to trust parties entering the pool
|
2014-12-09 02:17:57 +01:00
|
|
|
to behave themselves. If they don't it takes their money. */
|
|
|
|
|
|
|
|
cachedLastSuccess = 0;
|
|
|
|
cachedNumBlocks = 0;
|
|
|
|
unitTest = false;
|
|
|
|
txCollateral = CTransaction();
|
|
|
|
minBlockSpacing = 1;
|
2015-01-27 15:46:06 +01:00
|
|
|
lastNewBlock = 0;
|
2015-03-02 00:09:33 +01:00
|
|
|
strMasternodeSharedKey = "";
|
2015-03-06 23:17:51 +01:00
|
|
|
nTrickleInputsOutputs = 0;
|
2014-12-09 02:17:57 +01:00
|
|
|
|
|
|
|
SetNull();
|
|
|
|
}
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/** Process a Darksend message using the Darksend protocol
|
|
|
|
* \param pfrom
|
|
|
|
* \param strCommand lower case command string; valid values are:
|
|
|
|
* Command | Description
|
|
|
|
* -------- | -----------------
|
|
|
|
* dsa | Darksend Acceptable
|
|
|
|
* dsc | Darksend Complete
|
|
|
|
* dsf | Darksend Final tx
|
|
|
|
* dsi | Darksend vIn
|
|
|
|
* dsq | Darksend Queue
|
|
|
|
* dss | Darksend Signal Final Tx
|
|
|
|
* dssu | Darksend status update
|
|
|
|
* dssub | Darksend Subscribe To
|
|
|
|
* \param vRecv
|
|
|
|
*/
|
2015-03-02 00:09:33 +01:00
|
|
|
void ProcessMessageDarksend(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
2015-02-23 21:07:37 +01:00
|
|
|
|
2015-01-02 15:49:44 +01:00
|
|
|
void InitCollateralAddress(){
|
|
|
|
std::string strAddress = "";
|
|
|
|
if(Params().NetworkID() == CChainParams::MAIN) {
|
|
|
|
strAddress = "Xq19GqFvajRrEdDHYRKGYjTsQfpV5jyipF";
|
|
|
|
} else {
|
|
|
|
strAddress = "y1EZuxhhNMAUofTBEeLqGE1bJrpC2TWRNp";
|
|
|
|
}
|
|
|
|
SetCollateralAddress(strAddress);
|
|
|
|
}
|
|
|
|
|
2014-12-09 02:17:57 +01:00
|
|
|
void SetMinBlockSpacing(int minBlockSpacingIn){
|
|
|
|
minBlockSpacing = minBlockSpacingIn;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SetCollateralAddress(std::string strAddress);
|
2014-12-28 15:46:39 +01:00
|
|
|
void Reset();
|
2015-03-02 00:09:33 +01:00
|
|
|
bool Downgrade();
|
2015-03-06 23:17:51 +01:00
|
|
|
bool TrickleInputsOutputs();
|
2015-03-02 00:09:33 +01:00
|
|
|
|
2014-12-09 02:17:57 +01:00
|
|
|
void SetNull(bool clearEverything=false);
|
|
|
|
|
|
|
|
void UnlockCoins();
|
|
|
|
|
|
|
|
bool IsNull() const
|
|
|
|
{
|
|
|
|
return (state == POOL_STATUS_ACCEPTING_ENTRIES && entries.empty() && myEntries.empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetState() const
|
|
|
|
{
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetEntriesCount() const
|
|
|
|
{
|
|
|
|
if(fMasterNode){
|
|
|
|
return entries.size();
|
|
|
|
} else {
|
|
|
|
return entriesCount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Get the time the last entry was accepted (time in UTC milliseconds)
|
2014-12-09 02:17:57 +01:00
|
|
|
int GetLastEntryAccepted() const
|
|
|
|
{
|
|
|
|
return lastEntryAccepted;
|
|
|
|
}
|
|
|
|
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Get the count of the accepted entries
|
2014-12-09 02:17:57 +01:00
|
|
|
int GetCountEntriesAccepted() const
|
|
|
|
{
|
|
|
|
return countEntriesAccepted;
|
|
|
|
}
|
|
|
|
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Get the client's transaction count
|
2014-12-09 02:17:57 +01:00
|
|
|
int GetMyTransactionCount() const
|
|
|
|
{
|
|
|
|
return myEntries.size();
|
|
|
|
}
|
|
|
|
|
2015-03-06 08:24:34 +01:00
|
|
|
// Set the 'state' value, with some logging and capturing when the state changed
|
2014-12-09 02:17:57 +01:00
|
|
|
void UpdateState(unsigned int newState)
|
|
|
|
{
|
|
|
|
if (fMasterNode && (newState == POOL_STATUS_ERROR || newState == POOL_STATUS_SUCCESS)){
|
2015-03-05 09:10:15 +01:00
|
|
|
LogPrintf("CDarksendPool::UpdateState() - Can't set state to ERROR or SUCCESS as a Masternode. \n");
|
2014-12-09 02:17:57 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-03-02 00:09:33 +01:00
|
|
|
LogPrintf("CDarksendPool::UpdateState() == %d | %d \n", state, newState);
|
2014-12-09 02:17:57 +01:00
|
|
|
if(state != newState){
|
|
|
|
lastTimeChanged = GetTimeMillis();
|
|
|
|
if(fMasterNode) {
|
2015-03-02 00:09:33 +01:00
|
|
|
RelayStatus(darkSendPool.sessionID, darkSendPool.GetState(), darkSendPool.GetEntriesCount(), MASTERNODE_RESET);
|
2014-12-09 02:17:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
state = newState;
|
|
|
|
}
|
|
|
|
|
2015-03-06 08:24:34 +01:00
|
|
|
/// Get the maximum number of transactions for the pool
|
2014-12-09 02:17:57 +01:00
|
|
|
int GetMaxPoolTransactions()
|
|
|
|
{
|
|
|
|
//if we're on testnet, just use two transactions per merge
|
2015-03-02 00:09:33 +01:00
|
|
|
if(Params().NetworkID() == CChainParams::TESTNET || Params().NetworkID() == CChainParams::REGTEST) return POOL_MAX_TRANSACTIONS_TESTNET;
|
2014-12-09 02:17:57 +01:00
|
|
|
|
|
|
|
//use the production amount
|
|
|
|
return POOL_MAX_TRANSACTIONS;
|
|
|
|
}
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Do we have enough users to take entries?
|
2014-12-09 02:17:57 +01:00
|
|
|
bool IsSessionReady(){
|
|
|
|
return sessionUsers >= GetMaxPoolTransactions();
|
|
|
|
}
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Are these outputs compatible with other client in the pool?
|
2015-03-02 00:09:33 +01:00
|
|
|
bool IsCompatibleWithEntries(std::vector<CTxOut>& vout);
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Is this amount compatible with other client in the pool?
|
2014-12-09 02:17:57 +01:00
|
|
|
bool IsCompatibleWithSession(int64_t nAmount, CTransaction txCollateral, std::string& strReason);
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Passively run Darksend in the background according to the configuration in settings (only for QT)
|
2014-12-09 02:17:57 +01:00
|
|
|
bool DoAutomaticDenominating(bool fDryRun=false, bool ready=false);
|
2014-12-30 01:09:34 +01:00
|
|
|
bool PrepareDarksendDenominate();
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Check for process in Darksend
|
2014-12-09 02:17:57 +01:00
|
|
|
void Check();
|
2015-03-02 00:09:33 +01:00
|
|
|
void CheckFinalTransaction();
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Charge fees to bad actors (Charge clients a fee if they're abusive)
|
2014-12-09 02:17:57 +01:00
|
|
|
void ChargeFees();
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Rarely charge fees to pay miners
|
2014-12-09 02:17:57 +01:00
|
|
|
void ChargeRandomFees();
|
|
|
|
void CheckTimeout();
|
2015-03-02 00:09:33 +01:00
|
|
|
void CheckForCompleteQueue();
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Check to make sure a signature matches an input in the pool
|
2014-12-09 02:17:57 +01:00
|
|
|
bool SignatureValid(const CScript& newSig, const CTxIn& newVin);
|
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
|
|
|
/// Add a clients entry to the pool
|
2014-12-09 02:17:57 +01:00
|
|
|
bool AddEntry(const std::vector<CTxIn>& newInput, const int64_t& nAmount, const CTransaction& txCollateral, const std::vector<CTxOut>& newOutput, std::string& error);
|
2015-03-02 00:09:33 +01:00
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Add an anonymous output/inputs/sig
|
2015-03-02 00:09:33 +01:00
|
|
|
bool AddAnonymousOutput(const CTxOut& out) {return anonTx.AddOutput(out);}
|
|
|
|
bool AddAnonymousInput(const CTxIn& in) {return anonTx.AddInput(in);}
|
|
|
|
bool AddAnonymousSig(const CTxIn& in) {return anonTx.AddSig(in);}
|
|
|
|
bool AddRelaySignature(vector<unsigned char> vchMasternodeRelaySigIn, int nMasternodeBlockHeightIn, std::string strSharedKey) {
|
|
|
|
vchMasternodeRelaySig = vchMasternodeRelaySigIn;
|
|
|
|
nMasternodeBlockHeight = nMasternodeBlockHeightIn;
|
|
|
|
strMasternodeSharedKey = strSharedKey;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-03-06 08:28:25 +01:00
|
|
|
/// Add signature to a vin
|
2014-12-09 02:17:57 +01:00
|
|
|
bool AddScriptSig(const CTxIn& newVin);
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Check that all inputs are signed. (Are all inputs signed?)
|
2014-12-09 02:17:57 +01:00
|
|
|
bool SignaturesComplete();
|
2015-03-05 09:10:15 +01:00
|
|
|
/// As a client, send a transaction to a Masternode to start the denomination process
|
2014-12-09 02:17:57 +01:00
|
|
|
void SendDarksendDenominate(std::vector<CTxIn>& vin, std::vector<CTxOut>& vout, int64_t amount);
|
2015-03-05 09:10:15 +01:00
|
|
|
/// Get Masternode updates about the progress of Darksend
|
2014-12-09 02:17:57 +01:00
|
|
|
bool StatusUpdate(int newState, int newEntriesCount, int newAccepted, std::string& error, int newSessionID=0);
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// As a client, check and sign the final transaction
|
2014-12-09 02:17:57 +01:00
|
|
|
bool SignFinalTransaction(CTransaction& finalTransactionNew, CNode* node);
|
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Get the last valid block hash for a given modulus
|
2014-12-09 02:17:57 +01:00
|
|
|
bool GetLastValidBlockHash(uint256& hash, int mod=1, int nBlockHeight=0);
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Process a new block
|
2014-12-09 02:17:57 +01:00
|
|
|
void NewBlock();
|
|
|
|
void CompletedTransaction(bool error, std::string lastMessageNew);
|
|
|
|
void ClearLastMessage();
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Used for liquidity providers
|
2014-12-09 02:17:57 +01:00
|
|
|
bool SendRandomPaymentToSelf();
|
2015-03-18 18:19:13 +01:00
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Split up large inputs or make fee sized inputs
|
2015-01-25 22:18:26 +01:00
|
|
|
bool MakeCollateralAmounts();
|
2015-01-15 15:41:56 +01:00
|
|
|
bool CreateDenominated(int64_t nTotalValue);
|
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)
|
2014-12-09 02:17:57 +01:00
|
|
|
int GetDenominations(const std::vector<CTxOut>& vout);
|
2015-03-06 23:17:51 +01:00
|
|
|
int GetDenominations(const std::vector<CTxDSOut>& vout);
|
|
|
|
|
2014-12-28 00:45:07 +01:00
|
|
|
void GetDenominationsToString(int nDenom, std::string& strDenom);
|
2015-03-02 00:09:33 +01:00
|
|
|
|
2015-03-05 08:49:50 +01:00
|
|
|
/// Get the denominations for a specific amount of darkcoin.
|
2014-12-30 23:42:50 +01:00
|
|
|
int GetDenominationsByAmount(int64_t nAmount, int nDenomTarget=0);
|
2014-12-09 02:17:57 +01:00
|
|
|
int GetDenominationsByAmounts(std::vector<int64_t>& vecAmount);
|
|
|
|
|
|
|
|
|
2015-03-02 00:09:33 +01:00
|
|
|
//
|
|
|
|
// Relay Darksend Messages
|
|
|
|
//
|
|
|
|
|
|
|
|
void RelayFinalTransaction(const int sessionID, const CTransaction& txNew);
|
|
|
|
void RelaySignaturesAnon(std::vector<CTxIn>& vin);
|
|
|
|
void RelayInAnon(std::vector<CTxIn>& vin, std::vector<CTxOut>& vout);
|
2015-03-06 23:17:51 +01:00
|
|
|
void RelayIn(const std::vector<CTxDSIn>& vin, const int64_t& nAmount, const CTransaction& txCollateral, const std::vector<CTxDSOut>& vout);
|
2015-03-02 00:09:33 +01:00
|
|
|
void RelayStatus(const int sessionID, const int newState, const int newEntriesCount, const int newAccepted, const std::string error="");
|
|
|
|
void RelayCompletedTransaction(const int sessionID, const bool error, const std::string errorMessage);
|
|
|
|
};
|
2014-12-09 02:17:57 +01:00
|
|
|
|
|
|
|
void ThreadCheckDarkSendPool();
|
|
|
|
|
|
|
|
#endif
|