Dash Core  0.12.2.1
P2P Digital Currency
privatesend.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2017 The Dash Core developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 #include "privatesend.h"
5 
6 #include "activemasternode.h"
7 #include "consensus/validation.h"
8 #include "governance.h"
9 #include "init.h"
10 #include "instantx.h"
11 #include "masternode-payments.h"
12 #include "masternode-sync.h"
13 #include "masternodeman.h"
14 #include "messagesigner.h"
15 #include "script/sign.h"
16 #include "txmempool.h"
17 #include "util.h"
18 #include "utilmoneystr.h"
19 
20 #include <boost/lexical_cast.hpp>
21 
22 CDarkSendEntry::CDarkSendEntry(const std::vector<CTxIn>& vecTxIn, const std::vector<CTxOut>& vecTxOut, const CTransaction& txCollateral) :
23  txCollateral(txCollateral), addr(CService())
24 {
25  BOOST_FOREACH(CTxIn txin, vecTxIn)
26  vecTxDSIn.push_back(txin);
27  BOOST_FOREACH(CTxOut txout, vecTxOut)
28  vecTxDSOut.push_back(txout);
29 }
30 
32 {
33  BOOST_FOREACH(CTxDSIn& txdsin, vecTxDSIn) {
34  if(txdsin.prevout == txin.prevout && txdsin.nSequence == txin.nSequence) {
35  if(txdsin.fHasSig) return false;
36 
37  txdsin.scriptSig = txin.scriptSig;
38  txdsin.prevPubKey = txin.prevPubKey;
39  txdsin.fHasSig = true;
40 
41  return true;
42  }
43  }
44 
45  return false;
46 }
47 
49 {
50  if(!fMasterNode) return false;
51 
52  std::string strMessage = vin.ToString() + boost::lexical_cast<std::string>(nDenom) + boost::lexical_cast<std::string>(nTime) + boost::lexical_cast<std::string>(fReady);
53 
55  LogPrintf("CDarksendQueue::Sign -- SignMessage() failed, %s\n", ToString());
56  return false;
57  }
58 
60 }
61 
62 bool CDarksendQueue::CheckSignature(const CPubKey& pubKeyMasternode)
63 {
64  std::string strMessage = vin.ToString() + boost::lexical_cast<std::string>(nDenom) + boost::lexical_cast<std::string>(nTime) + boost::lexical_cast<std::string>(fReady);
65  std::string strError = "";
66 
67  if(!CMessageSigner::VerifyMessage(pubKeyMasternode, vchSig, strMessage, strError)) {
68  LogPrintf("CDarksendQueue::CheckSignature -- Got bad Masternode queue signature: %s; error: %s\n", ToString(), strError);
69  return false;
70  }
71 
72  return true;
73 }
74 
76 {
77  std::vector<CNode*> vNodesCopy = connman.CopyNodeVector();
78  BOOST_FOREACH(CNode* pnode, vNodesCopy)
80  connman.PushMessage(pnode, NetMsgType::DSQUEUE, (*this));
81 
82  connman.ReleaseNodeVector(vNodesCopy);
83  return true;
84 }
85 
87 {
88  if(!fMasterNode) return false;
89 
90  std::string strMessage = tx.GetHash().ToString() + boost::lexical_cast<std::string>(sigTime);
91 
93  LogPrintf("CDarksendBroadcastTx::Sign -- SignMessage() failed\n");
94  return false;
95  }
96 
98 }
99 
100 bool CDarksendBroadcastTx::CheckSignature(const CPubKey& pubKeyMasternode)
101 {
102  std::string strMessage = tx.GetHash().ToString() + boost::lexical_cast<std::string>(sigTime);
103  std::string strError = "";
104 
105  if(!CMessageSigner::VerifyMessage(pubKeyMasternode, vchSig, strMessage, strError)) {
106  LogPrintf("CDarksendBroadcastTx::CheckSignature -- Got bad dstx signature, error: %s\n", strError);
107  return false;
108  }
109 
110  return true;
111 }
112 
114 {
115  // expire confirmed DSTXes after ~1h since confirmation
116  return (nConfirmedHeight != -1) && (nHeight - nConfirmedHeight > 24);
117 }
118 
120 {
121  // Both sides
123  nSessionID = 0;
124  nSessionDenom = 0;
125  vecEntries.clear();
129 }
130 
132 {
133  switch(nState) {
134  case POOL_STATE_IDLE: return "IDLE";
135  case POOL_STATE_QUEUE: return "QUEUE";
136  case POOL_STATE_ACCEPTING_ENTRIES: return "ACCEPTING_ENTRIES";
137  case POOL_STATE_SIGNING: return "SIGNING";
138  case POOL_STATE_ERROR: return "ERROR";
139  case POOL_STATE_SUCCESS: return "SUCCESS";
140  default: return "UNKNOWN";
141  }
142 }
143 
144 // Definitions for static data members
145 std::vector<CAmount> CPrivateSend::vecStandardDenominations;
146 std::map<uint256, CDarksendBroadcastTx> CPrivateSend::mapDSTX;
148 
150 {
151  vecStandardDenominations.clear();
152  /* Denominations
153 
154  A note about convertability. Within mixing pools, each denomination
155  is convertable to another.
156 
157  For example:
158  1DRK+1000 == (.1DRK+100)*10
159  10DRK+10000 == (1DRK+1000)*10
160  */
161  /* Disabled
162  vecStandardDenominations.push_back( (100 * COIN)+100000 );
163  */
164  vecStandardDenominations.push_back( (10 * COIN)+10000 );
165  vecStandardDenominations.push_back( (1 * COIN)+1000 );
166  vecStandardDenominations.push_back( (.1 * COIN)+100 );
167  vecStandardDenominations.push_back( (.01 * COIN)+10 );
168  /* Disabled till we need them
169  vecStandardDenominations.push_back( (.001 * COIN)+1 );
170  */
171 }
172 
173 // check to make sure the collateral provided by the client is valid
175 {
176  if(txCollateral.vout.empty()) return false;
177  if(txCollateral.nLockTime != 0) return false;
178 
179  CAmount nValueIn = 0;
180  CAmount nValueOut = 0;
181 
182  BOOST_FOREACH(const CTxOut txout, txCollateral.vout) {
183  nValueOut += txout.nValue;
184 
185  if(!txout.scriptPubKey.IsNormalPaymentScript()) {
186  LogPrintf ("CPrivateSend::IsCollateralValid -- Invalid Script, txCollateral=%s", txCollateral.ToString());
187  return false;
188  }
189  }
190 
191  BOOST_FOREACH(const CTxIn txin, txCollateral.vin) {
192  CCoins coins;
193  if(!GetUTXOCoins(txin.prevout, coins)) {
194  LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- Unknown inputs in collateral transaction, txCollateral=%s", txCollateral.ToString());
195  return false;
196  }
197  nValueIn += coins.vout[txin.prevout.n].nValue;
198  }
199 
200  //collateral transactions are required to pay out a small fee to the miners
201  if(nValueIn - nValueOut < GetCollateralAmount()) {
202  LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- did not include enough fees in transaction: fees: %d, txCollateral=%s", nValueOut - nValueIn, txCollateral.ToString());
203  return false;
204  }
205 
206  LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- %s", txCollateral.ToString());
207 
208  {
209  LOCK(cs_main);
210  CValidationState validationState;
211  if(!AcceptToMemoryPool(mempool, validationState, txCollateral, false, NULL, false, true, true)) {
212  LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- didn't pass AcceptToMemoryPool()\n");
213  return false;
214  }
215  }
216 
217  return true;
218 }
219 
220 /* Create a nice string to show the denominations
221  Function returns as follows (for 4 denominations):
222  ( bit on if present )
223  bit 0 - 100
224  bit 1 - 10
225  bit 2 - 1
226  bit 3 - .1
227  bit 4 and so on - out-of-bounds
228  none of above - non-denom
229 */
231 {
232  std::string strDenom = "";
233  int nMaxDenoms = vecStandardDenominations.size();
234 
235  if(nDenom >= (1 << nMaxDenoms)) {
236  return "out-of-bounds";
237  }
238 
239  for (int i = 0; i < nMaxDenoms; ++i) {
240  if(nDenom & (1 << i)) {
241  strDenom += (strDenom.empty() ? "" : "+") + FormatMoney(vecStandardDenominations[i]);
242  }
243  }
244 
245  if(strDenom.empty()) {
246  return "non-denom";
247  }
248 
249  return strDenom;
250 }
251 
252 int CPrivateSend::GetDenominations(const std::vector<CTxDSOut>& vecTxDSOut)
253 {
254  std::vector<CTxOut> vecTxOut;
255 
256  BOOST_FOREACH(CTxDSOut out, vecTxDSOut)
257  vecTxOut.push_back(out);
258 
259  return GetDenominations(vecTxOut);
260 }
261 
262 /* Return a bitshifted integer representing the denominations in this list
263  Function returns as follows (for 4 denominations):
264  ( bit on if present )
265  100 - bit 0
266  10 - bit 1
267  1 - bit 2
268  .1 - bit 3
269  non-denom - 0, all bits off
270 */
271 int CPrivateSend::GetDenominations(const std::vector<CTxOut>& vecTxOut, bool fSingleRandomDenom)
272 {
273  std::vector<std::pair<CAmount, int> > vecDenomUsed;
274 
275  // make a list of denominations, with zero uses
276  BOOST_FOREACH(CAmount nDenomValue, vecStandardDenominations)
277  vecDenomUsed.push_back(std::make_pair(nDenomValue, 0));
278 
279  // look for denominations and update uses to 1
280  BOOST_FOREACH(CTxOut txout, vecTxOut) {
281  bool found = false;
282  BOOST_FOREACH (PAIRTYPE(CAmount, int)& s, vecDenomUsed) {
283  if(txout.nValue == s.first) {
284  s.second = 1;
285  found = true;
286  }
287  }
288  if(!found) return 0;
289  }
290 
291  int nDenom = 0;
292  int c = 0;
293  // if the denomination is used, shift the bit on
294  BOOST_FOREACH (PAIRTYPE(CAmount, int)& s, vecDenomUsed) {
295  int bit = (fSingleRandomDenom ? GetRandInt(2) : 1) & s.second;
296  nDenom |= bit << c++;
297  if(fSingleRandomDenom && bit) break; // use just one random denomination
298  }
299 
300  return nDenom;
301 }
302 
303 bool CPrivateSend::GetDenominationsBits(int nDenom, std::vector<int> &vecBitsRet)
304 {
305  // ( bit on if present, 4 denominations example )
306  // bit 0 - 100DASH+1
307  // bit 1 - 10DASH+1
308  // bit 2 - 1DASH+1
309  // bit 3 - .1DASH+1
310 
311  int nMaxDenoms = vecStandardDenominations.size();
312 
313  if(nDenom >= (1 << nMaxDenoms)) return false;
314 
315  vecBitsRet.clear();
316 
317  for (int i = 0; i < nMaxDenoms; ++i) {
318  if(nDenom & (1 << i)) {
319  vecBitsRet.push_back(i);
320  }
321  }
322 
323  return !vecBitsRet.empty();
324 }
325 
326 int CPrivateSend::GetDenominationsByAmounts(const std::vector<CAmount>& vecAmount)
327 {
328  CScript scriptTmp = CScript();
329  std::vector<CTxOut> vecTxOut;
330 
331  BOOST_REVERSE_FOREACH(CAmount nAmount, vecAmount) {
332  CTxOut txout(nAmount, scriptTmp);
333  vecTxOut.push_back(txout);
334  }
335 
336  return GetDenominations(vecTxOut, true);
337 }
338 
340 {
341  switch (nMessageID) {
342  case ERR_ALREADY_HAVE: return _("Already have that input.");
343  case ERR_DENOM: return _("No matching denominations found for mixing.");
344  case ERR_ENTRIES_FULL: return _("Entries are full.");
345  case ERR_EXISTING_TX: return _("Not compatible with existing transactions.");
346  case ERR_FEES: return _("Transaction fees are too high.");
347  case ERR_INVALID_COLLATERAL: return _("Collateral not valid.");
348  case ERR_INVALID_INPUT: return _("Input is not valid.");
349  case ERR_INVALID_SCRIPT: return _("Invalid script detected.");
350  case ERR_INVALID_TX: return _("Transaction not valid.");
351  case ERR_MAXIMUM: return _("Entry exceeds maximum size.");
352  case ERR_MN_LIST: return _("Not in the Masternode list.");
353  case ERR_MODE: return _("Incompatible mode.");
354  case ERR_NON_STANDARD_PUBKEY: return _("Non-standard public key detected.");
355  case ERR_NOT_A_MN: return _("This is not a Masternode."); // not used
356  case ERR_QUEUE_FULL: return _("Masternode queue is full.");
357  case ERR_RECENT: return _("Last PrivateSend was too recent.");
358  case ERR_SESSION: return _("Session not complete!");
359  case ERR_MISSING_TX: return _("Missing input transaction information.");
360  case ERR_VERSION: return _("Incompatible version.");
361  case MSG_NOERR: return _("No errors detected.");
362  case MSG_SUCCESS: return _("Transaction created successfully.");
363  case MSG_ENTRIES_ADDED: return _("Your entries added successfully.");
364  default: return _("Unknown response.");
365  }
366 }
367 
369 {
370  LOCK(cs_mapdstx);
371  mapDSTX.insert(std::make_pair(dstx.tx.GetHash(), dstx));
372 }
373 
375 {
376  LOCK(cs_mapdstx);
377  auto it = mapDSTX.find(hash);
378  return (it == mapDSTX.end()) ? CDarksendBroadcastTx() : it->second;
379 }
380 
381 void CPrivateSend::CheckDSTXes(int nHeight)
382 {
383  LOCK(cs_mapdstx);
384  std::map<uint256, CDarksendBroadcastTx>::iterator it = mapDSTX.begin();
385  while(it != mapDSTX.end()) {
386  if (it->second.IsExpired(nHeight)) {
387  mapDSTX.erase(it++);
388  } else {
389  ++it;
390  }
391  }
392  LogPrint("privatesend", "CPrivateSend::CheckDSTXes -- mapDSTX.size()=%llu\n", mapDSTX.size());
393 }
394 
395 void CPrivateSend::SyncTransaction(const CTransaction& tx, const CBlock* pblock)
396 {
397  if (tx.IsCoinBase()) return;
398 
400 
401  uint256 txHash = tx.GetHash();
402  if (!mapDSTX.count(txHash)) return;
403 
404  // When tx is 0-confirmed or conflicted, pblock is NULL and nConfirmedHeight should be set to -1
405  CBlockIndex* pblockindex = NULL;
406  if(pblock) {
407  uint256 blockHash = pblock->GetHash();
408  BlockMap::iterator mi = mapBlockIndex.find(blockHash);
409  if(mi == mapBlockIndex.end() || !mi->second) {
410  // shouldn't happen
411  LogPrint("privatesend", "CPrivateSendClient::SyncTransaction -- Failed to find block %s\n", blockHash.ToString());
412  return;
413  }
414  pblockindex = mi->second;
415  }
416  mapDSTX[txHash].SetConfirmedHeight(pblockindex ? pblockindex->nHeight : -1);
417  LogPrint("privatesend", "CPrivateSendClient::SyncTransaction -- txid=%s\n", txHash.ToString());
418 }
419 
420 //TODO: Rename/move to core
422 {
423  if(fLiteMode) return; // disable all Dash specific functionality
424 
425  static bool fOneThread;
426  if(fOneThread) return;
427  fOneThread = true;
428 
429  // Make this thread recognisable as the PrivateSend thread
430  RenameThread("dash-ps");
431 
432  unsigned int nTick = 0;
433 
434  while (true)
435  {
436  MilliSleep(1000);
437 
438  // try to sync from all available nodes, one step at a time
439  masternodeSync.ProcessTick(connman);
440 
442 
443  nTick++;
444 
445  // make sure to check all masternodes first
446  mnodeman.Check();
447 
448  // check if we should activate or ping every few minutes,
449  // slightly postpone first run to give net thread a chance to connect to some peers
450  if(nTick % MASTERNODE_MIN_MNP_SECONDS == 15)
451  activeMasternode.ManageState(connman);
452 
453  if(nTick % 60 == 0) {
455  mnodeman.CheckAndRemove(connman);
458  }
459  if(fMasterNode && (nTick % (60 * 5) == 0)) {
461  }
462 
463  if(nTick % (60 * 5) == 0) {
464  governance.DoMaintenance(connman);
465  }
466  }
467  }
468 }
uint32_t n
Definition: transaction.h:19
std::string GetStateString() const
CMasternodeMan mnodeman
CMasternodeSync masternodeSync
const uint32_t nLockTime
Definition: transaction.h:235
Definition: coins.h:73
PoolState nState
Definition: privatesend.h:287
void MilliSleep(int64_t n)
Definition: utiltime.cpp:63
CActiveMasternode activeMasternode
int GetRandInt(int nMax)
Definition: random.cpp:109
bool fHasSig
Definition: privatesend.h:80
uint32_t nSequence
Definition: transaction.h:63
const char * DSQUEUE
Definition: protocol.cpp:61
bool ShutdownRequested()
Definition: init.cpp:168
bool GetUTXOCoins(const COutPoint &outpoint, CCoins &coins)
Definition: validation.cpp:446
static const CAmount COIN
Definition: amount.h:16
static std::string GetDenominationsToString(int nDenom)
void ProcessTick(CConnman &connman)
CCriticalSection cs_main
Definition: validation.cpp:62
CAmount nValue
Definition: transaction.h:136
bool AddScriptSig(const CTxIn &txin)
Definition: privatesend.cpp:31
Definition: net.h:108
static CAmount GetCollateralAmount()
Definition: privatesend.h:349
void CheckAndRemove()
Definition: instantx.cpp:631
std::vector< CTxIn > vin
Definition: transaction.h:306
bool AcceptToMemoryPool(CTxMemPool &pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, bool *pfMissingInputs, bool fOverrideMempoolLimit, bool fRejectAbsurdFee, bool fDryRun)
std::vector< unsigned char > vchSig
Definition: privatesend.h:229
static std::vector< CAmount > vecStandardDenominations
Definition: privatesend.h:321
static void SyncTransaction(const CTransaction &tx, const CBlock *pblock)
void RenameThread(const char *name)
Definition: util.cpp:873
PoolMessage
Definition: privatesend.h:30
static int GetDenominations(const std::vector< CTxOut > &vecTxOut, bool fSingleRandomDenom=false)
Get the denominations for a list of outputs (returns a bitshifted integer)
static void AddDSTX(const CDarksendBroadcastTx &dstx)
bool CheckSignature(const CPubKey &pubKeyMasternode)
std::vector< CTxDSIn > vecTxDSIn
Definition: privatesend.h:118
void Check()
Check all Masternodes.
bool fMasterNode
Definition: util.cpp:108
CScript scriptSig
Definition: transaction.h:62
int64_t CAmount
Definition: amount.h:14
bool IsExpired(int nHeight)
bool fLiteMode
Definition: util.cpp:109
#define LOCK2(cs1, cs2)
Definition: sync.h:169
void ReleaseNodeVector(const std::vector< CNode *> &vecNodes)
Definition: net.cpp:2908
std::vector< CTxOut > vout
unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are d...
Definition: coins.h:80
#define LogPrintf(...)
Definition: util.h:98
std::string ToString()
Definition: privatesend.h:205
COutPoint prevout
Definition: transaction.h:61
Definition: net.h:661
CMasternodePayments mnpayments
static int LogPrint(const char *category, const char *format)
Definition: util.h:126
#define LOCK(cs)
Definition: sync.h:168
std::string ToString() const
Definition: transaction.cpp:36
static CCriticalSection cs_mapdstx
Definition: privatesend.h:324
bool Relay(CConnman &connman)
Definition: privatesend.cpp:75
void DoFullVerificationStep(CConnman &connman)
bool IsNormalPaymentScript() const
Definition: script.cpp:203
int64_t nTimeLastSuccessfulStep
Definition: privatesend.h:288
CInstantSend instantsend
Definition: instantx.cpp:30
static std::string GetMessageByID(PoolMessage nMessageID)
static bool VerifyMessage(const CPubKey pubkey, const std::vector< unsigned char > &vchSig, const std::string strMessage, std::string &strErrorRet)
Verify the message signature, returns true if succcessful.
std::string ToString() const
Definition: uint256.cpp:65
static bool GetDenominationsBits(int nDenom, std::vector< int > &vecBitsRet)
void ProcessMasternodeConnections(CConnman &connman)
std::vector< CNode * > CopyNodeVector()
Definition: net.cpp:2896
CMutableTransaction finalMutableTransaction
Definition: privatesend.h:292
void DoMaintenance(CConnman &connman)
Definition: governance.cpp:663
std::string FormatMoney(const CAmount &n)
CScript scriptPubKey
Definition: transaction.h:137
static const int MASTERNODE_MIN_MNP_SECONDS
Definition: masternode.h:18
static std::map< uint256, CDarksendBroadcastTx > mapDSTX
Definition: privatesend.h:322
std::vector< CTxOut > vout
Definition: transaction.h:307
void ManageState(CConnman &connman)
Manage state of active Masternode.
const std::vector< CTxIn > vin
Definition: transaction.h:233
std::vector< CDarkSendEntry > vecEntries
Definition: privatesend.h:285
CTxMemPool mempool
int64_t GetTimeMillis()
Definition: utiltime.cpp:34
const uint256 & GetHash() const
Definition: transaction.h:262
bool IsBlockchainSynced()
std::string ToString() const
static const int MIN_PRIVATESEND_PEER_PROTO_VERSION
minimum peer version accepted by mixing pool
Definition: privatesend.h:25
bool IsCoinBase() const
Definition: transaction.h:284
bool CheckSignature(const CPubKey &pubKeyMasternode)
Check if we have a valid Masternode address.
Definition: privatesend.cpp:62
void CheckAndRemove(CConnman &connman)
Check all Masternodes and remove inactive.
const std::vector< CTxOut > vout
Definition: transaction.h:234
static bool IsCollateralValid(const CTransaction &txCollateral)
If the collateral is valid given by a client.
Definition: pubkey.h:37
static bool SignMessage(const std::string strMessage, std::vector< unsigned char > &vchSigRet, const CKey key)
Sign the message, returns true if successful.
CGovernanceManager governance
Definition: governance.cpp:17
static void InitStandardDenominations()
Definition: block.h:73
uint256 GetHash() const
Definition: block.cpp:13
void ThreadCheckPrivateSend(CConnman &connman)
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:113
#define PAIRTYPE(t1, t2)
static int GetDenominationsByAmounts(const std::vector< CAmount > &vecAmount)
Get the denominations for a specific amount of dash.
BlockMap mapBlockIndex
Definition: validation.cpp:64
static void CheckDSTXes(int nHeight)
static CDarksendBroadcastTx GetDSTX(const uint256 &hash)
void PushMessage(CNode *pnode, const std::string &sCommand, Args &&... args)
Definition: net.h:199
std::atomic< int > nVersion
Definition: net.h:692
std::string _(const char *psz)
Definition: util.h:84
std::vector< CTxDSOut > vecTxDSOut
Definition: privatesend.h:119
CScript prevPubKey
Definition: transaction.h:64
std::vector< unsigned char > vchSig
Definition: privatesend.h:156