Merge #928: Refactor All The Things - part1
86d8505 Refactor CActiveMasternode + move strMasterNodeAddr to CActiveMasternode a005c79 Refactor InstantSend + new lock cs_instantsend to protect maps on CleanTransactionLocksList() + new DEFAULT_INSTANTSEND_DEPTH constant + rename MIN_INSTANTX_PROTO_VERSION to MIN_INSTANTSEND_PROTO_VERSION and bump it d24182c Refactor Privatesend + decouple from util.h and version.h + more functions for CDarksendBroadcastTx: constructors, signing, serialization + move from rand() to insecure_rand() in general but to GetRand() for session id + fix defaults
This commit is contained in:
parent
08703cebe6
commit
5a8c0c9b9d
@ -2,35 +2,36 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "addrman.h"
|
||||
#include "protocol.h"
|
||||
#include "activemasternode.h"
|
||||
#include "masternode.h"
|
||||
#include "masternode-sync.h"
|
||||
#include "masternodeman.h"
|
||||
#include "spork.h"
|
||||
#include "protocol.h"
|
||||
|
||||
//
|
||||
// Bootup the Masternode, look for a 1000DRK input and register on the network
|
||||
//
|
||||
void CActiveMasternode::ManageStatus()
|
||||
extern CWallet* pwalletMain;
|
||||
|
||||
// Keep track of the active Masternode
|
||||
CActiveMasternode activeMasternode;
|
||||
|
||||
// Bootup the Masternode, look for a 1000DASH input and register on the network
|
||||
void CActiveMasternode::ManageState()
|
||||
{
|
||||
std::string errorMessage;
|
||||
std::string strErrorMessage;
|
||||
|
||||
if(!fMasterNode) return;
|
||||
|
||||
if (fDebug) LogPrintf("CActiveMasternode::ManageStatus() - Begin\n");
|
||||
if (fDebug) LogPrintf("CActiveMasternode::ManageState -- Begin\n");
|
||||
|
||||
//need correct blocks to send ping
|
||||
if(Params().NetworkIDString() != CBaseChainParams::REGTEST && !masternodeSync.IsBlockchainSynced()) {
|
||||
status = ACTIVE_MASTERNODE_SYNC_IN_PROCESS;
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - %s\n", GetStatus());
|
||||
nState = ACTIVE_MASTERNODE_SYNC_IN_PROCESS;
|
||||
LogPrintf("CActiveMasternode::ManageState -- %s\n", GetStatus());
|
||||
return;
|
||||
}
|
||||
|
||||
if(status == ACTIVE_MASTERNODE_SYNC_IN_PROCESS) status = ACTIVE_MASTERNODE_INITIAL;
|
||||
if(nState == ACTIVE_MASTERNODE_SYNC_IN_PROCESS) nState = ACTIVE_MASTERNODE_INITIAL;
|
||||
|
||||
if(status == ACTIVE_MASTERNODE_INITIAL) {
|
||||
if(nState == ACTIVE_MASTERNODE_INITIAL) {
|
||||
CMasternode *pmn;
|
||||
pmn = mnodeman.Find(pubKeyMasternode);
|
||||
if(pmn != NULL) {
|
||||
@ -40,28 +41,28 @@ void CActiveMasternode::ManageStatus()
|
||||
}
|
||||
}
|
||||
|
||||
if(status != ACTIVE_MASTERNODE_STARTED) {
|
||||
if(nState != ACTIVE_MASTERNODE_STARTED) {
|
||||
|
||||
// Set defaults
|
||||
status = ACTIVE_MASTERNODE_NOT_CAPABLE;
|
||||
notCapableReason = "";
|
||||
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
|
||||
strNotCapableReason = "";
|
||||
|
||||
if(pwalletMain->IsLocked()){
|
||||
notCapableReason = "Wallet is locked.";
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
|
||||
if(pwalletMain->IsLocked()) {
|
||||
strNotCapableReason = "Wallet is locked.";
|
||||
LogPrintf("CActiveMasternode::ManageState -- not capable: %s\n", strNotCapableReason);
|
||||
return;
|
||||
}
|
||||
|
||||
if(pwalletMain->GetBalance() == 0){
|
||||
notCapableReason = "Hot node, waiting for remote activation.";
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
|
||||
if(pwalletMain->GetBalance() == 0) {
|
||||
nState = ACTIVE_MASTERNODE_INITIAL;
|
||||
LogPrintf("CActiveMasternode::ManageState() -- %s\n", GetStatus());
|
||||
return;
|
||||
}
|
||||
|
||||
if(strMasterNodeAddr.empty()) {
|
||||
if(!GetLocal(service)) {
|
||||
notCapableReason = "Can't detect external address. Please use the masternodeaddr configuration option.";
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
|
||||
strNotCapableReason = "Can't detect external address. Please use the masternodeaddr configuration option.";
|
||||
LogPrintf("CActiveMasternode::ManageState -- not capable: %s\n", strNotCapableReason);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -71,126 +72,124 @@ void CActiveMasternode::ManageStatus()
|
||||
int mainnetDefaultPort = Params(CBaseChainParams::MAIN).GetDefaultPort();
|
||||
if(Params().NetworkIDString() == CBaseChainParams::MAIN) {
|
||||
if(service.GetPort() != mainnetDefaultPort) {
|
||||
notCapableReason = strprintf("Invalid port: %u - only %d is supported on mainnet.", service.GetPort(), mainnetDefaultPort);
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
|
||||
strNotCapableReason = strprintf("Invalid port: %u - only %d is supported on mainnet.", service.GetPort(), mainnetDefaultPort);
|
||||
LogPrintf("CActiveMasternode::ManageState -- not capable: %s\n", strNotCapableReason);
|
||||
return;
|
||||
}
|
||||
} else if(service.GetPort() == mainnetDefaultPort) {
|
||||
notCapableReason = strprintf("Invalid port: %u - %d is only supported on mainnet.", service.GetPort(), mainnetDefaultPort);
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
|
||||
strNotCapableReason = strprintf("Invalid port: %u - %d is only supported on mainnet.", service.GetPort(), mainnetDefaultPort);
|
||||
LogPrintf("CActiveMasternode::ManageState -- not capable: %s\n", strNotCapableReason);
|
||||
return;
|
||||
}
|
||||
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - Checking inbound connection to '%s'\n", service.ToString());
|
||||
LogPrintf("CActiveMasternode::ManageState -- Checking inbound connection to '%s'\n", service.ToString());
|
||||
|
||||
if(!ConnectNode((CAddress)service, NULL, true)){
|
||||
notCapableReason = "Could not connect to " + service.ToString();
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
|
||||
if(!ConnectNode((CAddress)service, NULL, true)) {
|
||||
strNotCapableReason = "Could not connect to " + service.ToString();
|
||||
LogPrintf("CActiveMasternode::ManageState -- not capable: %s\n", strNotCapableReason);
|
||||
return;
|
||||
}
|
||||
|
||||
// Choose coins to use
|
||||
CPubKey pubKeyCollateralAddress;
|
||||
CKey keyCollateralAddress;
|
||||
CPubKey pubKeyCollateral;
|
||||
CKey keyCollateral;
|
||||
|
||||
if(pwalletMain->GetMasternodeVinAndKeys(vin, pubKeyCollateralAddress, keyCollateralAddress)) {
|
||||
if(pwalletMain->GetMasternodeVinAndKeys(vin, pubKeyCollateral, keyCollateral)) {
|
||||
|
||||
if(GetInputAge(vin) < Params().GetConsensus().nMasternodeMinimumConfirmations){
|
||||
status = ACTIVE_MASTERNODE_INPUT_TOO_NEW;
|
||||
notCapableReason = strprintf("%s - %d confirmations", GetStatus(), GetInputAge(vin));
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - %s\n", notCapableReason);
|
||||
int nInputAge = GetInputAge(vin);
|
||||
if(nInputAge < Params().GetConsensus().nMasternodeMinimumConfirmations){
|
||||
nState = ACTIVE_MASTERNODE_INPUT_TOO_NEW;
|
||||
strNotCapableReason = strprintf("%s - %d confirmations", GetStatus(), nInputAge);
|
||||
LogPrintf("CActiveMasternode::ManageState -- %s\n", strNotCapableReason);
|
||||
return;
|
||||
}
|
||||
|
||||
LOCK(pwalletMain->cs_wallet);
|
||||
pwalletMain->LockCoin(vin.prevout);
|
||||
|
||||
// send to all nodes
|
||||
CMasternodeBroadcast mnb;
|
||||
if(!CMasternodeBroadcast::Create(vin, service, keyCollateralAddress, pubKeyCollateralAddress, keyMasternode, pubKeyMasternode, errorMessage, mnb)) {
|
||||
notCapableReason = "Error on CreateBroadcast: " + errorMessage;
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - %s\n", notCapableReason);
|
||||
if(!CMasternodeBroadcast::Create(vin, service, keyCollateral, pubKeyCollateral, keyMasternode, pubKeyMasternode, strErrorMessage, mnb)) {
|
||||
strNotCapableReason = "Error on CMasternodeBroadcast::Create -- " + strErrorMessage;
|
||||
LogPrintf("CActiveMasternode::ManageState -- %s\n", strNotCapableReason);
|
||||
return;
|
||||
}
|
||||
|
||||
//update to masternode list
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - Update Masternode List\n");
|
||||
LogPrintf("CActiveMasternode::ManageState -- Update Masternode List\n");
|
||||
mnodeman.UpdateMasternodeList(mnb);
|
||||
|
||||
//send to all peers
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - Relay broadcast vin = %s\n", vin.ToString());
|
||||
LogPrintf("CActiveMasternode::ManageState -- Relay broadcast, vin=%s\n", vin.ToString());
|
||||
mnb.Relay();
|
||||
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - Is capable master node!\n");
|
||||
status = ACTIVE_MASTERNODE_STARTED;
|
||||
LogPrintf("CActiveMasternode::ManageState -- Is capable master node!\n");
|
||||
nState = ACTIVE_MASTERNODE_STARTED;
|
||||
|
||||
return;
|
||||
} else {
|
||||
notCapableReason = "Could not find suitable coins!";
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - %s\n", notCapableReason);
|
||||
strNotCapableReason = "Could not find suitable coins!";
|
||||
LogPrintf("CActiveMasternode::ManageState -- %s\n", strNotCapableReason);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//send to all peers
|
||||
if(!SendMasternodePing(errorMessage)) {
|
||||
LogPrintf("CActiveMasternode::ManageStatus() - Error on Ping: %s\n", errorMessage);
|
||||
if(!SendMasternodePing(strErrorMessage)) {
|
||||
LogPrintf("CActiveMasternode::ManageState -- Error on SendMasternodePing(): %s\n", strErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
std::string CActiveMasternode::GetStatus() {
|
||||
switch (status) {
|
||||
case ACTIVE_MASTERNODE_INITIAL: return "Node just started, not yet activated";
|
||||
case ACTIVE_MASTERNODE_SYNC_IN_PROCESS: return "Sync in progress. Must wait until sync is complete to start Masternode";
|
||||
case ACTIVE_MASTERNODE_INPUT_TOO_NEW: return strprintf("Masternode input must have at least %d confirmations", Params().GetConsensus().nMasternodeMinimumConfirmations);
|
||||
case ACTIVE_MASTERNODE_NOT_CAPABLE: return "Not capable masternode: " + notCapableReason;
|
||||
case ACTIVE_MASTERNODE_STARTED: return "Masternode successfully started";
|
||||
default: return "unknown";
|
||||
std::string CActiveMasternode::GetStatus()
|
||||
{
|
||||
switch (nState) {
|
||||
case ACTIVE_MASTERNODE_INITIAL: return "Node just started, not yet activated";
|
||||
case ACTIVE_MASTERNODE_SYNC_IN_PROCESS: return "Sync in progress. Must wait until sync is complete to start Masternode";
|
||||
case ACTIVE_MASTERNODE_INPUT_TOO_NEW: return strprintf("Masternode input must have at least %d confirmations", Params().GetConsensus().nMasternodeMinimumConfirmations);
|
||||
case ACTIVE_MASTERNODE_NOT_CAPABLE: return "Not capable masternode: " + strNotCapableReason;
|
||||
case ACTIVE_MASTERNODE_STARTED: return "Masternode successfully started";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
bool CActiveMasternode::SendMasternodePing(std::string& errorMessage) {
|
||||
if(status != ACTIVE_MASTERNODE_STARTED) {
|
||||
errorMessage = "Masternode is not in a running status";
|
||||
bool CActiveMasternode::SendMasternodePing(std::string& strErrorMessage)
|
||||
{
|
||||
if(nState != ACTIVE_MASTERNODE_STARTED) {
|
||||
strErrorMessage = "Masternode is not in a running status";
|
||||
return false;
|
||||
}
|
||||
|
||||
LogPrintf("CActiveMasternode::SendMasternodePing() - Relay Masternode Ping vin = %s\n", vin.ToString());
|
||||
|
||||
CMasternodePing mnp(vin);
|
||||
if(!mnp.Sign(keyMasternode, pubKeyMasternode))
|
||||
{
|
||||
errorMessage = "Couldn't sign Masternode Ping";
|
||||
if(!mnp.Sign(keyMasternode, pubKeyMasternode)) {
|
||||
strErrorMessage = "Couldn't sign Masternode Ping";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update lastPing for our masternode in Masternode list
|
||||
CMasternode* pmn = mnodeman.Find(vin);
|
||||
if(pmn != NULL)
|
||||
{
|
||||
if(pmn->IsPingedWithin(MASTERNODE_PING_SECONDS, mnp.sigTime)){
|
||||
errorMessage = "Too early to send Masternode Ping";
|
||||
if(pmn != NULL) {
|
||||
if(pmn->IsPingedWithin(MASTERNODE_MIN_MNP_SECONDS, mnp.sigTime)) {
|
||||
strErrorMessage = "Too early to send Masternode Ping";
|
||||
return false;
|
||||
}
|
||||
|
||||
pmn->lastPing = mnp;
|
||||
mnodeman.mapSeenMasternodePing.insert(make_pair(mnp.GetHash(), mnp));
|
||||
mnodeman.mapSeenMasternodePing.insert(std::make_pair(mnp.GetHash(), mnp));
|
||||
|
||||
//mnodeman.mapSeenMasternodeBroadcast.lastPing is probably outdated, so we'll update it
|
||||
CMasternodeBroadcast mnb(*pmn);
|
||||
uint256 hash = mnb.GetHash();
|
||||
if(mnodeman.mapSeenMasternodeBroadcast.count(hash)) mnodeman.mapSeenMasternodeBroadcast[hash].lastPing = mnp;
|
||||
if(mnodeman.mapSeenMasternodeBroadcast.count(hash))
|
||||
mnodeman.mapSeenMasternodeBroadcast[hash].lastPing = mnp;
|
||||
|
||||
LogPrintf("CActiveMasternode::SendMasternodePing -- Relaying ping, collateral=%s\n", vin.ToString());
|
||||
mnp.Relay();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Seems like we are trying to send a ping while the Masternode is not registered in the network
|
||||
errorMessage = "PrivateSend Masternode List doesn't include our Masternode, shutting down Masternode pinging service! " + vin.ToString();
|
||||
status = ACTIVE_MASTERNODE_NOT_CAPABLE;
|
||||
notCapableReason = errorMessage;
|
||||
strErrorMessage = "PrivateSend Masternode List doesn't include our Masternode, shutting down Masternode pinging service! " + vin.ToString();
|
||||
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
|
||||
strNotCapableReason = strErrorMessage;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -200,13 +199,13 @@ bool CActiveMasternode::EnableHotColdMasterNode(CTxIn& newVin, CService& newServ
|
||||
{
|
||||
if(!fMasterNode) return false;
|
||||
|
||||
status = ACTIVE_MASTERNODE_STARTED;
|
||||
nState = ACTIVE_MASTERNODE_STARTED;
|
||||
|
||||
//The values below are needed for signing mnping messages going forward
|
||||
vin = newVin;
|
||||
service = newService;
|
||||
|
||||
LogPrintf("CActiveMasternode::EnableHotColdMasterNode() - Enabled! You may shut down the cold daemon.\n");
|
||||
LogPrintf("CActiveMasternode::EnableHotColdMasterNode -- Enabled! You may shut down the cold daemon.\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,23 +1,23 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Copyright (c) 2014-2016 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.
|
||||
|
||||
#ifndef ACTIVEMASTERNODE_H
|
||||
#define ACTIVEMASTERNODE_H
|
||||
|
||||
#include "sync.h"
|
||||
#include "net.h"
|
||||
#include "key.h"
|
||||
#include "init.h"
|
||||
#include "wallet/wallet.h"
|
||||
#include "darksend.h"
|
||||
#include "masternode.h"
|
||||
|
||||
#define ACTIVE_MASTERNODE_INITIAL 0 // initial state
|
||||
#define ACTIVE_MASTERNODE_SYNC_IN_PROCESS 1
|
||||
#define ACTIVE_MASTERNODE_INPUT_TOO_NEW 2
|
||||
#define ACTIVE_MASTERNODE_NOT_CAPABLE 3
|
||||
#define ACTIVE_MASTERNODE_STARTED 4
|
||||
class CActiveMasternode;
|
||||
|
||||
static const int ACTIVE_MASTERNODE_INITIAL = 0; // initial state
|
||||
static const int ACTIVE_MASTERNODE_SYNC_IN_PROCESS = 1;
|
||||
static const int ACTIVE_MASTERNODE_INPUT_TOO_NEW = 2;
|
||||
static const int ACTIVE_MASTERNODE_NOT_CAPABLE = 3;
|
||||
static const int ACTIVE_MASTERNODE_STARTED = 4;
|
||||
|
||||
extern CActiveMasternode activeMasternode;
|
||||
|
||||
// Responsible for activating the Masternode and pinging the network
|
||||
class CActiveMasternode
|
||||
@ -27,11 +27,12 @@ private:
|
||||
mutable CCriticalSection cs;
|
||||
|
||||
/// Ping Masternode
|
||||
bool SendMasternodePing(std::string& errorMessage);
|
||||
bool SendMasternodePing(std::string& strErrorMessage);
|
||||
|
||||
public:
|
||||
// Initialized by init.cpp
|
||||
// Keys for the main Masternode
|
||||
std::string strMasterNodeAddr;
|
||||
// Keys for the active Masternode
|
||||
CPubKey pubKeyMasternode;
|
||||
CKey keyMasternode;
|
||||
|
||||
@ -39,19 +40,16 @@ public:
|
||||
CTxIn vin;
|
||||
CService service;
|
||||
|
||||
int status;
|
||||
std::string notCapableReason;
|
||||
int nState; // should be one of ACTIVE_MASTERNODE_XXXX
|
||||
std::string strNotCapableReason;
|
||||
|
||||
CActiveMasternode()
|
||||
{
|
||||
status = ACTIVE_MASTERNODE_INITIAL;
|
||||
}
|
||||
CActiveMasternode() : nState(ACTIVE_MASTERNODE_INITIAL) {}
|
||||
|
||||
/// Manage state of active Masternode
|
||||
void ManageState();
|
||||
|
||||
/// Manage status of main Masternode
|
||||
void ManageStatus();
|
||||
std::string GetStatus();
|
||||
|
||||
|
||||
/// Enable cold wallet mode (run a Masternode with no funds)
|
||||
bool EnableHotColdMasterNode(CTxIn& vin, CService& addr);
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
#include "darksend.h"
|
||||
#include "darksend-relay.h"
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ bool CDarkSendRelay::Sign(std::string strSharedKey)
|
||||
CPubKey pubkey2;
|
||||
std::string errorMessage = "";
|
||||
|
||||
if(!darkSendSigner.SetKey(strSharedKey, errorMessage, key2, pubkey2))
|
||||
if(!darkSendSigner.GetKeysFromSecret(strSharedKey, errorMessage, key2, pubkey2))
|
||||
{
|
||||
LogPrintf("CDarkSendRelay():Sign - ERROR: Invalid shared key: '%s'\n", errorMessage);
|
||||
return false;
|
||||
@ -69,7 +69,7 @@ bool CDarkSendRelay::VerifyMessage(std::string strSharedKey)
|
||||
CPubKey pubkey2;
|
||||
std::string errorMessage = "";
|
||||
|
||||
if(!darkSendSigner.SetKey(strSharedKey, errorMessage, key2, pubkey2))
|
||||
if(!darkSendSigner.GetKeysFromSecret(strSharedKey, errorMessage, key2, pubkey2))
|
||||
{
|
||||
LogPrintf("CDarkSendRelay()::VerifyMessage - ERROR: Invalid shared key: '%s'\n", errorMessage);
|
||||
return false;
|
||||
@ -85,7 +85,7 @@ bool CDarkSendRelay::VerifyMessage(std::string strSharedKey)
|
||||
|
||||
void CDarkSendRelay::Relay()
|
||||
{
|
||||
int nCount = std::min(mnodeman.CountEnabled(MIN_POOL_PEER_PROTO_VERSION), 20);
|
||||
int nCount = std::min(mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION), 20);
|
||||
int nRank1 = (rand() % nCount)+1;
|
||||
int nRank2 = (rand() % nCount)+1;
|
||||
|
||||
@ -101,7 +101,7 @@ void CDarkSendRelay::Relay()
|
||||
|
||||
void CDarkSendRelay::RelayThroughNode(int nRank)
|
||||
{
|
||||
CMasternode* pmn = mnodeman.GetMasternodeByRank(nRank, nBlockHeight, MIN_POOL_PEER_PROTO_VERSION);
|
||||
CMasternode* pmn = mnodeman.GetMasternodeByRank(nRank, nBlockHeight, MIN_PRIVATESEND_PEER_PROTO_VERSION);
|
||||
|
||||
if(pmn != NULL){
|
||||
//printf("RelayThroughNode %s\n", pmn->addr.ToString().c_str());
|
||||
|
2310
src/darksend.cpp
2310
src/darksend.cpp
File diff suppressed because it is too large
Load Diff
630
src/darksend.h
630
src/darksend.h
@ -5,63 +5,68 @@
|
||||
#ifndef DARKSEND_H
|
||||
#define DARKSEND_H
|
||||
|
||||
#include "main.h"
|
||||
#include "sync.h"
|
||||
#include "activemasternode.h"
|
||||
#include "masternodeman.h"
|
||||
#include "darksend-relay.h"
|
||||
#include "masternode.h"
|
||||
#include "wallet/wallet.h"
|
||||
|
||||
class CTxIn;
|
||||
class CDarksendPool;
|
||||
class CDarkSendSigner;
|
||||
class CMasterNodeVote;
|
||||
class CBitcoinAddress;
|
||||
class CDarksendQueue;
|
||||
class CDarksendBroadcastTx;
|
||||
class CActiveMasternode;
|
||||
|
||||
// pool states for mixing
|
||||
#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
|
||||
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
|
||||
|
||||
// status update message constants
|
||||
#define MASTERNODE_ACCEPTED 1
|
||||
#define MASTERNODE_REJECTED 0
|
||||
#define MASTERNODE_RESET -1
|
||||
static const int MASTERNODE_ACCEPTED = 1;
|
||||
static const int MASTERNODE_REJECTED = 0;
|
||||
static const int MASTERNODE_RESET = -1;
|
||||
|
||||
#define DARKSEND_AUTO_TIMEOUT_MIN 5
|
||||
#define DARKSEND_AUTO_TIMEOUT_MAX 15
|
||||
#define DARKSEND_QUEUE_TIMEOUT 30
|
||||
#define DARKSEND_SIGNING_TIMEOUT 15
|
||||
// timeouts
|
||||
static const int DARKSEND_AUTO_TIMEOUT_MIN = 5;
|
||||
static const int DARKSEND_AUTO_TIMEOUT_MAX = 15;
|
||||
static const int DARKSEND_QUEUE_TIMEOUT = 30;
|
||||
static const int DARKSEND_SIGNING_TIMEOUT = 15;
|
||||
|
||||
// used for anonymous relaying of inputs/outputs/sigs
|
||||
#define DARKSEND_RELAY_IN 1
|
||||
#define DARKSEND_RELAY_OUT 2
|
||||
#define DARKSEND_RELAY_SIG 3
|
||||
//! minimum peer version accepted by DarksendPool
|
||||
static const int MIN_PRIVATESEND_PEER_PROTO_VERSION = 70201;
|
||||
|
||||
static const CAmount DARKSEND_COLLATERAL = 0.01 * COIN;
|
||||
static const CAmount DARKSEND_POOL_MAX = 999.99 * COIN;
|
||||
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;
|
||||
|
||||
static const CAmount DARKSEND_COLLATERAL = (0.01*COIN);
|
||||
static const CAmount DARKSEND_POOL_MAX = (999.99*COIN);
|
||||
static const CAmount DENOMS_COUNT_MAX = 100;
|
||||
// Warn user if mixing in gui or try to create backup if mixing in daemon mode
|
||||
// when we have only this many keys left
|
||||
static const int PS_KEYS_THRESHOLD_WARNING = 100;
|
||||
static const int PRIVATESEND_KEYS_THRESHOLD_WARNING = 100;
|
||||
// Stop mixing completely, it's too dangerous to continue when we have only this many keys left
|
||||
static const int PS_KEYS_THRESHOLD_STOP = 50;
|
||||
static const int PRIVATESEND_KEYS_THRESHOLD_STOP = 50;
|
||||
|
||||
extern int nPrivateSendRounds;
|
||||
extern int nPrivateSendAmount;
|
||||
extern int nLiquidityProvider;
|
||||
extern bool fEnablePrivateSend;
|
||||
extern bool fPrivateSendMultiSession;
|
||||
|
||||
// The main object for accessing mixing
|
||||
extern CDarksendPool darkSendPool;
|
||||
// A helper object for signing messages from Masternodes
|
||||
extern CDarkSendSigner darkSendSigner;
|
||||
extern std::vector<CDarksendQueue> vecDarksendQueue;
|
||||
extern map<uint256, CDarksendBroadcastTx> mapDarksendBroadcastTxes;
|
||||
extern CActiveMasternode activeMasternode;
|
||||
|
||||
/** Holds an Darksend input
|
||||
extern std::map<uint256, CDarksendBroadcastTx> mapDarksendBroadcastTxes;
|
||||
extern std::vector<CAmount> vecPrivateSendDenominations;
|
||||
|
||||
/** Holds an mixing input
|
||||
*/
|
||||
class CTxDSIn : public CTxIn
|
||||
{
|
||||
@ -69,114 +74,69 @@ public:
|
||||
bool fHasSig; // flag to indicate if signed
|
||||
int nSentTimes; //times we've sent this anonymously
|
||||
|
||||
CTxDSIn(const CTxIn& in)
|
||||
{
|
||||
prevout = in.prevout;
|
||||
scriptSig = in.scriptSig;
|
||||
prevPubKey = in.prevPubKey;
|
||||
nSequence = in.nSequence;
|
||||
nSentTimes = 0;
|
||||
fHasSig = false;
|
||||
}
|
||||
CTxDSIn(const CTxIn& txin) :
|
||||
CTxIn(txin),
|
||||
fHasSig(false),
|
||||
nSentTimes(0) {}
|
||||
};
|
||||
|
||||
/** Holds an Darksend output
|
||||
/** Holds an mixing output
|
||||
*/
|
||||
class CTxDSOut : public CTxOut
|
||||
{
|
||||
public:
|
||||
int nSentTimes; //times we've sent this anonymously
|
||||
|
||||
CTxDSOut(const CTxOut& out)
|
||||
{
|
||||
nValue = out.nValue;
|
||||
nRounds = out.nRounds;
|
||||
scriptPubKey = out.scriptPubKey;
|
||||
nSentTimes = 0;
|
||||
}
|
||||
CTxDSOut(const CTxOut& out) :
|
||||
CTxOut(out),
|
||||
nSentTimes(0) {}
|
||||
};
|
||||
|
||||
// A clients transaction in the darksend pool
|
||||
// A clients transaction in the mixing pool
|
||||
class CDarkSendEntry
|
||||
{
|
||||
public:
|
||||
std::vector<CTxDSIn> vecTxDSIn;
|
||||
std::vector<CTxDSOut> vecTxDSOut;
|
||||
CTransaction txCollateral;
|
||||
CAmount nAmount;
|
||||
int64_t nTimeAdded; // time in UTC milliseconds
|
||||
bool isSet;
|
||||
std::vector<CTxDSIn> sev;
|
||||
std::vector<CTxDSOut> vout;
|
||||
CAmount amount;
|
||||
CTransaction collateral;
|
||||
CTransaction txSupporting;
|
||||
int64_t addedTime; // time in UTC milliseconds
|
||||
|
||||
CDarkSendEntry()
|
||||
{
|
||||
isSet = false;
|
||||
collateral = CTransaction();
|
||||
amount = 0;
|
||||
}
|
||||
CDarkSendEntry() :
|
||||
txCollateral(CTransaction()),
|
||||
nAmount(0),
|
||||
nTimeAdded(0),
|
||||
isSet(false) {}
|
||||
|
||||
/// Add entries to use for Darksend
|
||||
bool Add(const std::vector<CTxIn> vinIn, CAmount amountIn, const CTransaction collateralIn, const std::vector<CTxOut> voutIn)
|
||||
{
|
||||
if(isSet){return false;}
|
||||
/// Add entries to use for mixing
|
||||
bool Add(const std::vector<CTxIn> vecTxIn, CAmount nAmount, const CTransaction txCollateral, const std::vector<CTxOut> vecTxOut);
|
||||
|
||||
BOOST_FOREACH(const CTxIn& in, vinIn)
|
||||
sev.push_back(in);
|
||||
bool AddScriptSig(const CTxIn& txin);
|
||||
|
||||
BOOST_FOREACH(const CTxOut& out, voutIn)
|
||||
vout.push_back(out);
|
||||
|
||||
amount = amountIn;
|
||||
collateral = collateralIn;
|
||||
isSet = true;
|
||||
addedTime = GetTime();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AddSig(const CTxIn& vin)
|
||||
{
|
||||
BOOST_FOREACH(CTxDSIn& s, sev) {
|
||||
if(s.prevout == vin.prevout && s.nSequence == vin.nSequence){
|
||||
if(s.fHasSig){return false;}
|
||||
s.scriptSig = vin.scriptSig;
|
||||
s.prevPubKey = vin.prevPubKey;
|
||||
s.fHasSig = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsExpired()
|
||||
{
|
||||
return (GetTime() - addedTime) > DARKSEND_QUEUE_TIMEOUT;// 30 seconds
|
||||
}
|
||||
bool IsExpired() { return GetTime() - nTimeAdded > DARKSEND_QUEUE_TIMEOUT; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A currently inprogress Darksend merge and denomination information
|
||||
* A currently inprogress mixing merge and denomination information
|
||||
*/
|
||||
class CDarksendQueue
|
||||
{
|
||||
public:
|
||||
CTxIn vin;
|
||||
int64_t time;
|
||||
int nDenom;
|
||||
bool ready; //ready for submit
|
||||
CTxIn vin;
|
||||
int64_t nTime;
|
||||
bool fReady; //ready for submit
|
||||
std::vector<unsigned char> vchSig;
|
||||
|
||||
CDarksendQueue()
|
||||
{
|
||||
nDenom = 0;
|
||||
vin = CTxIn();
|
||||
time = 0;
|
||||
vchSig.clear();
|
||||
ready = false;
|
||||
}
|
||||
CDarksendQueue() { CDarksendQueue(0, CTxIn(), 0, false); }
|
||||
|
||||
CDarksendQueue(int nDenom, CTxIn vin, int64_t nTime, bool fReady) :
|
||||
nDenom(nDenom),
|
||||
vin(vin),
|
||||
nTime(nTime),
|
||||
fReady(fReady) { vchSig = std::vector<unsigned char>(); }
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
@ -184,35 +144,15 @@ public:
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(nDenom);
|
||||
READWRITE(vin);
|
||||
READWRITE(time);
|
||||
READWRITE(ready);
|
||||
READWRITE(nTime);
|
||||
READWRITE(fReady);
|
||||
READWRITE(vchSig);
|
||||
}
|
||||
|
||||
bool GetAddress(CService &addr)
|
||||
{
|
||||
CMasternode* pmn = mnodeman.Find(vin);
|
||||
if(pmn != NULL)
|
||||
{
|
||||
addr = pmn->addr;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool GetAddress(CService &addrRet);
|
||||
bool GetProtocolVersion(int &nProtocolVersionRet);
|
||||
|
||||
/// Get the protocol version
|
||||
bool GetProtocolVersion(int &protocolVersion)
|
||||
{
|
||||
CMasternode* pmn = mnodeman.Find(vin);
|
||||
if(pmn != NULL)
|
||||
{
|
||||
protocolVersion = pmn->protocolVersion;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Sign this Darksend transaction
|
||||
/** Sign this mixing transaction
|
||||
* \return true if all conditions are met:
|
||||
* 1) we have an active Masternode,
|
||||
* 2) we have a valid Masternode private key,
|
||||
@ -220,29 +160,42 @@ public:
|
||||
* 4) we verified the message successfully
|
||||
*/
|
||||
bool Sign();
|
||||
|
||||
bool Relay();
|
||||
|
||||
/// Is this Darksend expired?
|
||||
bool IsExpired()
|
||||
{
|
||||
return (GetTime() - time) > DARKSEND_QUEUE_TIMEOUT;// 30 seconds
|
||||
}
|
||||
|
||||
/// Check if we have a valid Masternode address
|
||||
bool CheckSignature();
|
||||
|
||||
bool Relay();
|
||||
|
||||
/// Is this queue expired?
|
||||
bool IsExpired() { return GetTime() - nTime > DARKSEND_QUEUE_TIMEOUT; }
|
||||
};
|
||||
|
||||
/** Helper class to store Darksend transaction (tx) information.
|
||||
/** Helper class to store mixing transaction (tx) information.
|
||||
*/
|
||||
class CDarksendBroadcastTx
|
||||
{
|
||||
public:
|
||||
CTransaction tx;
|
||||
CTxIn vin;
|
||||
vector<unsigned char> vchSig;
|
||||
std::vector<unsigned char> vchSig;
|
||||
int64_t sigTime;
|
||||
|
||||
CDarksendBroadcastTx() { CDarksendBroadcastTx(CTransaction(), CTxIn(), 0); }
|
||||
|
||||
CDarksendBroadcastTx(CTransaction tx, CTxIn vin, int64_t sigTime) :
|
||||
tx(tx), vin(vin), sigTime(sigTime) { vchSig = std::vector<unsigned char>(); }
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
/** Helper object for signing and checking signatures
|
||||
@ -251,59 +204,20 @@ class CDarkSendSigner
|
||||
{
|
||||
public:
|
||||
/// Is the inputs associated with this public key? (and there is 1000 DASH - checking if valid masternode)
|
||||
bool IsVinAssociatedWithPubkey(CTxIn& vin, CPubKey& pubkey);
|
||||
bool IsVinAssociatedWithPubkey(const CTxIn& vin, const CPubKey& pubkey);
|
||||
/// Set the private/public key values, returns true if successful
|
||||
bool SetKey(std::string strSecret, std::string& errorMessage, CKey& key, CPubKey& pubkey);
|
||||
bool GetKeysFromSecret(std::string strSecret, std::string& strErrorMessageRet, CKey& keyRet, CPubKey& pubkeyRet);
|
||||
/// Sign the message, returns true if successful
|
||||
bool SignMessage(std::string strMessage, std::string& errorMessage, std::vector<unsigned char>& vchSig, CKey key);
|
||||
bool SignMessage(std::string strMessage, std::string& strErrorMessageRet, std::vector<unsigned char>& vchSigRet, CKey key);
|
||||
/// Verify the message, returns true if succcessful
|
||||
bool VerifyMessage(CPubKey pubkey, std::vector<unsigned char>& vchSig, std::string strMessage, std::string& errorMessage);
|
||||
bool VerifyMessage(CPubKey pubkey, const std::vector<unsigned char>& vchSig, std::string strMessage, std::string& strErrorMessageRet);
|
||||
};
|
||||
|
||||
/** Used to keep track of current status of Darksend pool
|
||||
/** Used to keep track of current status of mixing pool
|
||||
*/
|
||||
class CDarksendPool
|
||||
{
|
||||
private:
|
||||
mutable CCriticalSection cs_darksend;
|
||||
|
||||
std::vector<CDarkSendEntry> entries; // Masternode/clients entries
|
||||
CMutableTransaction finalMutableTransaction; // the finalized transaction ready for signing
|
||||
|
||||
int64_t lastTimeChanged; // last time the 'state' changed, in UTC milliseconds
|
||||
|
||||
unsigned int state; // should be one of the POOL_STATUS_XXX values
|
||||
unsigned int entriesCount;
|
||||
unsigned int lastEntryAccepted;
|
||||
unsigned int countEntriesAccepted;
|
||||
|
||||
std::vector<CTxIn> lockedCoins;
|
||||
|
||||
std::string lastMessage;
|
||||
bool unitTest;
|
||||
|
||||
int sessionID;
|
||||
|
||||
int sessionUsers; //N Users have said they'll join
|
||||
bool sessionFoundMasternode; //If we've found a compatible Masternode
|
||||
std::vector<CTransaction> vecSessionCollateral;
|
||||
|
||||
int cachedLastSuccess;
|
||||
|
||||
int minBlockSpacing; //required blocks between mixes
|
||||
CMutableTransaction txCollateral;
|
||||
|
||||
int64_t lastNewBlock;
|
||||
|
||||
// Keep track of current block index
|
||||
const CBlockIndex *pCurrentBlockIndex;
|
||||
|
||||
std::vector<CAmount> darkSendDenominationsSkipped;
|
||||
|
||||
//debugging data
|
||||
std::string strAutoDenomResult;
|
||||
|
||||
public:
|
||||
enum messages {
|
||||
ERR_ALREADY_HAVE,
|
||||
ERR_DENOM,
|
||||
@ -329,219 +243,177 @@ public:
|
||||
MSG_ENTRIES_ADDED
|
||||
};
|
||||
|
||||
CMasternode* pSubmittedToMasternode;
|
||||
int sessionDenom; //Users must submit an denom matching this
|
||||
int cachedNumBlocks; //used for the overview screen
|
||||
bool fCreateAutoBackups; //builtin support for automatic backups
|
||||
mutable CCriticalSection cs_darksend;
|
||||
|
||||
CDarksendPool()
|
||||
{
|
||||
/* Darksend uses collateral addresses to trust parties entering the pool
|
||||
to behave themselves. If they don't it takes their money. */
|
||||
// The current mixing sessions in progress on the network
|
||||
std::vector<CDarksendQueue> vecDarksendQueue;
|
||||
// Keep track of the used Masternodes
|
||||
std::vector<CTxIn> vecMasternodesUsed;
|
||||
|
||||
cachedLastSuccess = 0;
|
||||
cachedNumBlocks = std::numeric_limits<int>::max();
|
||||
unitTest = false;
|
||||
txCollateral = CMutableTransaction();
|
||||
minBlockSpacing = 0;
|
||||
lastNewBlock = 0;
|
||||
fCreateAutoBackups = true;
|
||||
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
|
||||
|
||||
SetNull();
|
||||
}
|
||||
unsigned int nState; // should be one of the POOL_STATE_XXX values
|
||||
int64_t nLastTimeChanged; // last time the 'state' changed, in UTC milliseconds
|
||||
|
||||
/** 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
|
||||
*/
|
||||
void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
||||
int nCachedLastSuccessBlock;
|
||||
int nMinBlockSpacing; //required blocks between mixes
|
||||
const CBlockIndex *pCurrentBlockIndex; // Keep track of current block index
|
||||
|
||||
void ClearSkippedDenominations() {
|
||||
darkSendDenominationsSkipped.clear();
|
||||
}
|
||||
int nSessionID;
|
||||
int nSessionUsers; //N Users have said they'll join
|
||||
bool fSessionFoundMasternode; //If we've found a compatible Masternode
|
||||
|
||||
bool IsDenomSkipped(CAmount denom) {
|
||||
BOOST_FOREACH(CAmount d, darkSendDenominationsSkipped) {
|
||||
if (d == denom) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
unsigned int nEntriesCount;
|
||||
bool fLastEntryAccepted;
|
||||
unsigned int nAcceptedEntriesCount;
|
||||
|
||||
void InitDenominations() {
|
||||
darkSendDenominations.clear();
|
||||
/* Denominations
|
||||
std::string strLastMessage;
|
||||
std::string strAutoDenomResult;
|
||||
|
||||
A note about convertability. Within Darksend pools, each denomination
|
||||
is convertable to another.
|
||||
bool fUnitTest;
|
||||
|
||||
For example:
|
||||
1DRK+1000 == (.1DRK+100)*10
|
||||
10DRK+10000 == (1DRK+1000)*10
|
||||
*/
|
||||
darkSendDenominations.push_back( (100 * COIN)+100000 );
|
||||
darkSendDenominations.push_back( (10 * COIN)+10000 );
|
||||
darkSendDenominations.push_back( (1 * COIN)+1000 );
|
||||
darkSendDenominations.push_back( (.1 * COIN)+100 );
|
||||
/* Disabled till we need them
|
||||
darkSendDenominations.push_back( (.01 * COIN)+10 );
|
||||
darkSendDenominations.push_back( (.001 * COIN)+1 );
|
||||
*/
|
||||
}
|
||||
CMutableTransaction txMyCollateral; // client side collateral
|
||||
CMutableTransaction finalMutableTransaction; // the finalized transaction ready for signing
|
||||
|
||||
void SetMinBlockSpacing(int minBlockSpacingIn){
|
||||
minBlockSpacing = minBlockSpacingIn;
|
||||
}
|
||||
/// Add a clients entry to the pool
|
||||
bool AddEntry(const std::vector<CTxIn>& vecTxInNew, const CAmount nAmount, const CTransaction& txCollateral, const std::vector<CTxOut>& vecTxOutNew, int& nErrorID);
|
||||
/// Add signature to a txin
|
||||
bool AddScriptSig(const CTxIn& txin);
|
||||
|
||||
void Reset();
|
||||
void SetNull();
|
||||
|
||||
void UnlockCoins();
|
||||
|
||||
bool IsNull() const
|
||||
{
|
||||
return state == POOL_STATUS_ACCEPTING_ENTRIES && entries.empty();
|
||||
}
|
||||
|
||||
int GetState() const
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
std::string GetStatus();
|
||||
|
||||
int GetEntriesCount() const
|
||||
{
|
||||
return entries.size();
|
||||
}
|
||||
|
||||
/// Get the time the last entry was accepted (time in UTC milliseconds)
|
||||
int GetLastEntryAccepted() const
|
||||
{
|
||||
return lastEntryAccepted;
|
||||
}
|
||||
|
||||
/// Get the count of the accepted entries
|
||||
int GetCountEntriesAccepted() const
|
||||
{
|
||||
return countEntriesAccepted;
|
||||
}
|
||||
|
||||
// Set the 'state' value, with some logging and capturing when the state changed
|
||||
void UpdateState(unsigned int newState)
|
||||
{
|
||||
if (fMasterNode && (newState == POOL_STATUS_ERROR || newState == POOL_STATUS_SUCCESS)){
|
||||
LogPrint("privatesend", "CDarksendPool::UpdateState() - Can't set state to ERROR or SUCCESS as a Masternode. \n");
|
||||
return;
|
||||
}
|
||||
|
||||
LogPrintf("CDarksendPool::UpdateState() == %d | %d \n", state, newState);
|
||||
if(state != newState){
|
||||
lastTimeChanged = GetTimeMillis();
|
||||
if(fMasterNode) {
|
||||
RelayStatus(darkSendPool.sessionID, darkSendPool.GetState(), darkSendPool.GetEntriesCount(), MASTERNODE_RESET);
|
||||
}
|
||||
}
|
||||
state = newState;
|
||||
}
|
||||
|
||||
/// Get the maximum number of transactions for the pool
|
||||
int GetMaxPoolTransactions()
|
||||
{
|
||||
return Params().PoolMaxTransactions();
|
||||
}
|
||||
|
||||
/// Do we have enough users to take entries?
|
||||
bool IsSessionReady(){
|
||||
return sessionUsers >= GetMaxPoolTransactions();
|
||||
}
|
||||
|
||||
/// Are these outputs compatible with other client in the pool?
|
||||
bool IsCompatibleWithEntries(std::vector<CTxOut>& vout);
|
||||
|
||||
/// Is this amount compatible with other client in the pool?
|
||||
bool IsCompatibleWithSession(int nDenom, CTransaction txCollateral, int &errorID);
|
||||
|
||||
/// Passively run Darksend in the background according to the configuration in settings
|
||||
bool DoAutomaticDenominating(bool fDryRun=false);
|
||||
bool PrepareDarksendDenominate();
|
||||
|
||||
/// Check for process in Darksend
|
||||
void Check();
|
||||
void CheckFinalTransaction();
|
||||
/// Charge fees to bad actors (Charge clients a fee if they're abusive)
|
||||
void ChargeFees();
|
||||
/// Rarely charge fees to pay miners
|
||||
void ChargeRandomFees();
|
||||
void CheckTimeout();
|
||||
void CheckForCompleteQueue();
|
||||
/// Check to make sure a signature matches an input in the pool
|
||||
bool SignatureValid(const CScript& newSig, const CTxIn& newVin);
|
||||
|
||||
/// Check for process
|
||||
void CheckPool();
|
||||
|
||||
void CheckFinalTransaction();
|
||||
|
||||
void CompletedTransaction(bool fError, int nErrorID);
|
||||
|
||||
/// Get the denominations for a specific amount of dash.
|
||||
int GetDenominationsByAmounts(const std::vector<CAmount>& vecAmount);
|
||||
|
||||
std::string GetMessageByID(int nMessageID);
|
||||
|
||||
/// Get the maximum number of transactions for the pool
|
||||
int GetMaxPoolTransactions() { return Params().PoolMaxTransactions(); }
|
||||
|
||||
/// Are these outputs compatible with other client in the pool?
|
||||
bool IsOutputsCompatibleWithSessionDenom(const std::vector<CTxOut>& vecTxOut);
|
||||
/// Is this nDenom compatible with other client in the pool?
|
||||
bool IsDenomCompatibleWithSession(int nDenom, CTransaction txCollateral, int &nErrorID);
|
||||
|
||||
/// If the collateral is valid given by a client
|
||||
bool IsCollateralValid(const CTransaction& txCollateral);
|
||||
/// Add a clients entry to the pool
|
||||
bool AddEntry(const std::vector<CTxIn>& newInput, const CAmount& nAmount, const CTransaction& txCollateral, const std::vector<CTxOut>& newOutput, int& errorID);
|
||||
/// Add signature to a vin
|
||||
bool AddScriptSig(const CTxIn& newVin);
|
||||
/// Check that all inputs are signed. (Are all inputs signed?)
|
||||
bool SignaturesComplete();
|
||||
/// As a client, send a transaction to a Masternode to start the denomination process
|
||||
void SendDarksendDenominate(std::vector<CTxIn>& vin, std::vector<CTxOut>& vout, CAmount amount);
|
||||
/// Get Masternode updates about the progress of Darksend
|
||||
bool StatusUpdate(int newState, int newEntriesCount, int newAccepted, int &errorID, int newSessionID=0);
|
||||
bool IsSignaturesComplete();
|
||||
/// Check to make sure a signature matches an input in the pool
|
||||
bool IsSignatureValid(const CScript& scriptSig, const CTxIn& txin);
|
||||
|
||||
/// As a client, check and sign the final transaction
|
||||
bool SignFinalTransaction(CTransaction& finalTransactionNew, CNode* node);
|
||||
bool IsDenomSkipped(CAmount nDenomValue) {
|
||||
return std::find(vecDenominationsSkipped.begin(), vecDenominationsSkipped.end(), nDenomValue) != vecDenominationsSkipped.end();
|
||||
}
|
||||
|
||||
/// Get the last valid block hash for a given modulus
|
||||
bool GetLastValidBlockHash(uint256& hash, int mod=1, int nBlockHeight=0);
|
||||
/// Process a new block
|
||||
void NewBlock();
|
||||
void CompletedTransaction(bool error, int errorID);
|
||||
void ClearLastMessage();
|
||||
bool IsNull() const { return nState == POOL_STATE_ACCEPTING_ENTRIES && vecEntries.empty(); }
|
||||
|
||||
/// Split up large inputs or make fee sized inputs
|
||||
bool MakeCollateralAmounts();
|
||||
bool MakeCollateralAmounts(const CompactTallyItem& tallyItem);
|
||||
/// Create denominations
|
||||
bool CreateDenominated();
|
||||
bool CreateDenominated(const CompactTallyItem& tallyItem);
|
||||
/// Split up large inputs or make fee sized inputs
|
||||
bool MakeCollateralAmounts();
|
||||
bool MakeCollateralAmounts(const CompactTallyItem& tallyItem);
|
||||
|
||||
bool PrepareDenominate();
|
||||
|
||||
/// Get the denominations for a list of outputs (returns a bitshifted integer)
|
||||
int GetDenominations(const std::vector<CTxOut>& vout, bool fSingleRandomDenom = false);
|
||||
int GetDenominations(const std::vector<CTxDSOut>& vout);
|
||||
/// 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);
|
||||
|
||||
void GetDenominationsToString(int nDenom, std::string& strDenom);
|
||||
/// As a client, check and sign the final transaction
|
||||
bool SignFinalTransaction(const CTransaction& finalTransactionNew, CNode* node);
|
||||
|
||||
/// Get the denominations for a specific amount of dash.
|
||||
int GetDenominationsByAmount(CAmount nAmount, int nDenomTarget=0); // is not used anymore?
|
||||
int GetDenominationsByAmounts(std::vector<CAmount>& vecAmount);
|
||||
|
||||
std::string GetMessageByID(int messageID);
|
||||
|
||||
//
|
||||
// Relay Darksend Messages
|
||||
//
|
||||
|
||||
void RelayFinalTransaction(const int sessionID, const CTransaction& txNew);
|
||||
/// Relay mixing Messages
|
||||
void RelayFinalTransaction(const CTransaction& txFinal);
|
||||
void RelaySignaturesAnon(std::vector<CTxIn>& vin);
|
||||
void RelayInAnon(std::vector<CTxIn>& vin, std::vector<CTxOut>& vout);
|
||||
void RelayIn(const std::vector<CTxDSIn>& vin, const CAmount& nAmount, const CTransaction& txCollateral, const std::vector<CTxDSOut>& vout);
|
||||
void RelayStatus(const int sessionID, const int newState, const int newEntriesCount, const int newAccepted, const int errorID=MSG_NOERR);
|
||||
void RelayCompletedTransaction(const int sessionID, const bool error, const int errorID);
|
||||
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);
|
||||
|
||||
void InitDenominations();
|
||||
void ClearSkippedDenominations() { vecDenominationsSkipped.clear(); }
|
||||
|
||||
/// Get the denominations for a list of outputs (returns a bitshifted integer)
|
||||
int GetDenominations(const std::vector<CTxOut>& vecTxOut, bool fSingleRandomDenom = false);
|
||||
int GetDenominations(const std::vector<CTxDSOut>& vecTxDSOut);
|
||||
std::string GetDenominationsToString(int nDenom);
|
||||
|
||||
void SetMinBlockSpacing(int nMinBlockSpacingIn) { nMinBlockSpacing = nMinBlockSpacingIn; }
|
||||
|
||||
void ResetPool();
|
||||
void SetNull();
|
||||
|
||||
void UnlockCoins();
|
||||
|
||||
int GetQueueSize() const { return vecDarksendQueue.size(); }
|
||||
int GetState() const { return nState; }
|
||||
std::string GetStatus();
|
||||
|
||||
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(); }
|
||||
|
||||
/// As a client, send a transaction to a Masternode to start the denomination process
|
||||
void SendDarksendDenominate(const std::vector<CTxIn>& vecTxIn, const std::vector<CTxOut>& vecTxOut, CAmount nAmount);
|
||||
|
||||
/// Process a new block
|
||||
void NewBlock();
|
||||
|
||||
void UpdatedBlockTip(const CBlockIndex *pindex);
|
||||
};
|
||||
|
51
src/init.cpp
51
src/init.cpp
@ -34,6 +34,8 @@
|
||||
#include "ui_interface.h"
|
||||
#include "util.h"
|
||||
#include "activemasternode.h"
|
||||
#include "instantx.h"
|
||||
#include "darksend.h"
|
||||
#include "masternode-payments.h"
|
||||
#include "masternode-sync.h"
|
||||
#include "masternodeman.h"
|
||||
@ -556,15 +558,15 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||
strUsage += HelpMessageOpt("-budgetvotemode=<mode>", _("Change automatic finalized budget voting behavior. mode=auto: Vote for only exact finalized budget match to my generated budget. (string, default: auto)"));
|
||||
|
||||
strUsage += HelpMessageGroup(_("PrivateSend options:"));
|
||||
strUsage += HelpMessageOpt("-enableprivatesend=<n>", strprintf(_("Enable use of automated PrivateSend for funds stored in this wallet (0-1, default: %u)"), fEnablePrivateSend));
|
||||
strUsage += HelpMessageOpt("-privatesendmultisession=<n>", strprintf(_("Enable multiple PrivateSend mixing sessions per block, experimental (0-1, default: %u)"), fPrivateSendMultiSession));
|
||||
strUsage += HelpMessageOpt("-privatesendrounds=<n>", strprintf(_("Use N separate masternodes to anonymize funds (2-8, default: %u)"), nPrivateSendRounds));
|
||||
strUsage += HelpMessageOpt("-privatesendamount=<n>", strprintf(_("Keep N DASH anonymized (default: %u)"), nPrivateSendAmount));
|
||||
strUsage += HelpMessageOpt("-enableprivatesend=<n>", strprintf(_("Enable use of automated PrivateSend for funds stored in this wallet (0-1, default: %u)"), 0));
|
||||
strUsage += HelpMessageOpt("-privatesendmultisession=<n>", strprintf(_("Enable multiple PrivateSend mixing sessions per block, experimental (0-1, default: %u)"), DEFAULT_PRIVATESEND_MULTISESSION));
|
||||
strUsage += HelpMessageOpt("-privatesendrounds=<n>", strprintf(_("Use N separate masternodes to anonymize funds (2-8, default: %u)"), DEFAULT_PRIVATESEND_ROUNDS));
|
||||
strUsage += HelpMessageOpt("-privatesendamount=<n>", strprintf(_("Keep N DASH anonymized (default: %u)"), DEFAULT_PRIVATESEND_AMOUNT));
|
||||
strUsage += HelpMessageOpt("-liquidityprovider=<n>", strprintf(_("Provide liquidity to PrivateSend by infrequently mixing coins on a continual basis (0-100, default: %u, 1=very frequent, high fees, 100=very infrequent, low fees)"), nLiquidityProvider));
|
||||
|
||||
strUsage += HelpMessageGroup(_("InstantSend options:"));
|
||||
strUsage += HelpMessageOpt("-enableinstantsend=<n>", strprintf(_("Enable InstantSend, show confirmations for locked transactions (0-1, default: %u)"), fEnableInstantSend));
|
||||
strUsage += HelpMessageOpt("-instantsenddepth=<n>", strprintf(_("Show N confirmations for a successfully locked transaction (0-9999, default: %u)"), nInstantSendDepth));
|
||||
strUsage += HelpMessageOpt("-enableinstantsend=<n>", strprintf(_("Enable InstantSend, show confirmations for locked transactions (0-1, default: %u)"), 1));
|
||||
strUsage += HelpMessageOpt("-instantsenddepth=<n>", strprintf(_("Show N confirmations for a successfully locked transaction (0-9999, default: %u)"), DEFAULT_INSTANTSEND_DEPTH));
|
||||
strUsage += HelpMessageOpt("-instantsendnotify=<cmd>", _("Execute command when a wallet IS transaction is successfully locked (%s in cmd is replaced by TxID)"));
|
||||
|
||||
|
||||
@ -1774,23 +1776,28 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
}
|
||||
|
||||
if(fMasterNode) {
|
||||
LogPrintf("IS DARKSEND MASTER NODE\n");
|
||||
strMasterNodeAddr = GetArg("-masternodeaddr", "");
|
||||
LogPrintf("MASTERNODE:\n");
|
||||
activeMasternode.strMasterNodeAddr = GetArg("-masternodeaddr", "");
|
||||
|
||||
LogPrintf(" addr %s\n", strMasterNodeAddr);
|
||||
|
||||
if(!strMasterNodeAddr.empty()){
|
||||
CService addrTest = CService(strMasterNodeAddr);
|
||||
if (!addrTest.IsValid()) {
|
||||
return InitError("Invalid -masternodeaddr address: " + strMasterNodeAddr);
|
||||
CService service;
|
||||
if(activeMasternode.strMasterNodeAddr.empty()) {
|
||||
if(!GetLocal(service)) {
|
||||
LogPrintf("Can't detect external address. Please consider using the masternodeaddr configuration option.\n");
|
||||
}
|
||||
} else {
|
||||
service = CService(activeMasternode.strMasterNodeAddr);
|
||||
if (!service.IsValid()) {
|
||||
return InitError("Invalid masternodeaddr: " + activeMasternode.strMasterNodeAddr);
|
||||
}
|
||||
}
|
||||
LogPrintf(" service: %s\n", service.ToString());
|
||||
|
||||
std::string strMasterNodePrivKey = GetArg("-masternodeprivkey", "");
|
||||
if(!strMasterNodePrivKey.empty()){
|
||||
std::string errorMessage;
|
||||
if(!strMasterNodePrivKey.empty()) {
|
||||
std::string strErrorMessage;
|
||||
|
||||
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, activeMasternode.keyMasternode, activeMasternode.pubKeyMasternode))
|
||||
if(!darkSendSigner.GetKeysFromSecret(strMasterNodePrivKey, strErrorMessage, activeMasternode.keyMasternode, activeMasternode.pubKeyMasternode))
|
||||
return InitError(_("Invalid masternodeprivkey. Please see documenation."));
|
||||
|
||||
LogPrintf(" pubKeyMasternode: %s\n", CBitcoinAddress(activeMasternode.pubKeyMasternode.GetID()).ToString());
|
||||
@ -1825,15 +1832,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
nLiquidityProvider = std::min(std::max(nLiquidityProvider, 0), 100);
|
||||
darkSendPool.SetMinBlockSpacing(nLiquidityProvider * 15);
|
||||
|
||||
fEnablePrivateSend = GetBoolArg("-enableprivatesend", fEnablePrivateSend);
|
||||
fPrivateSendMultiSession = GetBoolArg("-privatesendmultisession", fPrivateSendMultiSession);
|
||||
nPrivateSendRounds = GetArg("-privatesendrounds", nPrivateSendRounds);
|
||||
fEnablePrivateSend = GetBoolArg("-enableprivatesend", 0);
|
||||
fPrivateSendMultiSession = GetBoolArg("-privatesendmultisession", DEFAULT_PRIVATESEND_MULTISESSION);
|
||||
nPrivateSendRounds = GetArg("-privatesendrounds", DEFAULT_PRIVATESEND_ROUNDS);
|
||||
nPrivateSendRounds = std::min(std::max(nPrivateSendRounds, 1), 99999);
|
||||
nPrivateSendAmount = GetArg("-privatesendamount", nPrivateSendAmount);
|
||||
nPrivateSendAmount = GetArg("-privatesendamount", DEFAULT_PRIVATESEND_AMOUNT);
|
||||
nPrivateSendAmount = std::min(std::max(nPrivateSendAmount, 2), 999999);
|
||||
|
||||
fEnableInstantSend = GetBoolArg("-enableinstantsend", fEnableInstantSend);
|
||||
nInstantSendDepth = GetArg("-instantsenddepth", nInstantSendDepth);
|
||||
fEnableInstantSend = GetBoolArg("-enableinstantsend", 1);
|
||||
nInstantSendDepth = GetArg("-instantsenddepth", DEFAULT_INSTANTSEND_DEPTH);
|
||||
nInstantSendDepth = std::min(std::max(nInstantSendDepth, 0), 60);
|
||||
|
||||
//lite mode disables all Masternode and Darksend related functionality
|
||||
|
379
src/instantx.cpp
379
src/instantx.cpp
@ -20,33 +20,38 @@
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
extern CWallet* pwalletMain;
|
||||
|
||||
bool fEnableInstantSend = true;
|
||||
int nInstantSendDepth = DEFAULT_INSTANTSEND_DEPTH;
|
||||
int nCompleteTXLocks;
|
||||
|
||||
std::map<uint256, CTransaction> mapTxLockReq;
|
||||
std::map<uint256, CTransaction> mapTxLockReqRejected;
|
||||
std::map<uint256, CConsensusVote> mapTxLockVote;
|
||||
std::map<uint256, CTransactionLock> mapTxLocks;
|
||||
std::map<COutPoint, uint256> mapLockedInputs;
|
||||
|
||||
std::map<uint256, CTransactionLock> mapTxLocks;
|
||||
std::map<uint256, int64_t> mapUnknownVotes; //track votes with no tx for DOS
|
||||
int nCompleteTXLocks;
|
||||
|
||||
CCriticalSection cs_instantsend;
|
||||
|
||||
//txlock - Locks transaction
|
||||
//
|
||||
//step 1.) Broadcast intention to lock transaction inputs, "txlreg", CTransaction
|
||||
//step 2.) Top INSTANTX_SIGNATURES_TOTAL masternodes, open connect to top 1 masternode.
|
||||
//step 2.) Top INSTANTSEND_SIGNATURES_TOTAL masternodes, open connect to top 1 masternode.
|
||||
// Send "txvote", CTransaction, Signature, Approve
|
||||
//step 3.) Top 1 masternode, waits for INSTANTX_SIGNATURES_REQUIRED messages. Upon success, sends "txlock'
|
||||
//step 3.) Top 1 masternode, waits for INSTANTSEND_SIGNATURES_REQUIRED messages. Upon success, sends "txlock'
|
||||
|
||||
void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
||||
void ProcessMessageInstantSend(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
||||
{
|
||||
if(fLiteMode) return; //disable all darksend/masternode related functionality
|
||||
if(fLiteMode) return; // disable all Dash specific functionality
|
||||
if(!sporkManager.IsSporkActive(SPORK_2_INSTANTX)) return;
|
||||
if(!masternodeSync.IsBlockchainSynced()) return;
|
||||
|
||||
if (strCommand == NetMsgType::IX)
|
||||
{
|
||||
//LogPrintf("ProcessMessageInstantX::ix\n");
|
||||
//LogPrintf("ProcessMessageInstantSend\n");
|
||||
CDataStream vMsg(vRecv);
|
||||
CTransaction tx;
|
||||
vRecv >> tx;
|
||||
@ -60,13 +65,13 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
// have we seen it already?
|
||||
if(mapTxLockReq.count(inv.hash) || mapTxLockReqRejected.count(inv.hash)) return;
|
||||
// is it a valid one?
|
||||
if(!IsIXTXValid(tx)) return;
|
||||
if(!IsInstantSendTxValid(tx)) return;
|
||||
|
||||
BOOST_FOREACH(const CTxOut o, tx.vout){
|
||||
BOOST_FOREACH(const CTxOut o, tx.vout) {
|
||||
// IX supports normal scripts and unspendable scripts (used in DS collateral and Budget collateral).
|
||||
// TODO: Look into other script types that are normal and can be included
|
||||
if(!o.scriptPubKey.IsNormalPaymentScript() && !o.scriptPubKey.IsUnspendable()){
|
||||
LogPrintf("ProcessMessageInstantX::ix - Invalid Script %s", tx.ToString());
|
||||
if(!o.scriptPubKey.IsNormalPaymentScript() && !o.scriptPubKey.IsUnspendable()) {
|
||||
LogPrintf("ProcessMessageInstantSend -- Invalid Script %s", tx.ToString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -81,15 +86,14 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
LOCK(cs_main);
|
||||
fAccepted = AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs);
|
||||
}
|
||||
if (fAccepted)
|
||||
{
|
||||
if(fAccepted) {
|
||||
RelayInv(inv);
|
||||
|
||||
DoConsensusVote(tx, nBlockHeight);
|
||||
|
||||
mapTxLockReq.insert(make_pair(tx.GetHash(), tx));
|
||||
mapTxLockReq.insert(std::make_pair(tx.GetHash(), tx));
|
||||
|
||||
LogPrintf("ProcessMessageInstantX::ix - Transaction Lock Request: %s %s : accepted %s\n",
|
||||
LogPrintf("ProcessMessageInstantSend -- Transaction Lock Request: %s %s : accepted %s\n",
|
||||
pfrom->addr.ToString(), pfrom->cleanSubVer,
|
||||
tx.GetHash().ToString()
|
||||
);
|
||||
@ -97,7 +101,7 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
// Masternodes will sometimes propagate votes before the transaction is known to the client.
|
||||
// If this just happened - update transaction status, try forcing external script notification,
|
||||
// lock inputs and resolve conflicting locks
|
||||
if(IsLockedIXTransaction(tx.GetHash())) {
|
||||
if(IsLockedInstandSendTransaction(tx.GetHash())) {
|
||||
UpdateLockedTransaction(tx, true);
|
||||
LockTransactionInputs(tx);
|
||||
ResolveConflicts(tx);
|
||||
@ -106,11 +110,11 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
return;
|
||||
|
||||
} else {
|
||||
mapTxLockReqRejected.insert(make_pair(tx.GetHash(), tx));
|
||||
mapTxLockReqRejected.insert(std::make_pair(tx.GetHash(), tx));
|
||||
|
||||
// can we get the conflicting transaction as proof?
|
||||
|
||||
LogPrintf("ProcessMessageInstantX::ix - Transaction Lock Request: %s %s : rejected %s\n",
|
||||
LogPrintf("ProcessMessageInstantSend -- Transaction Lock Request: %s %s : rejected %s\n",
|
||||
pfrom->addr.ToString(), pfrom->cleanSubVer,
|
||||
tx.GetHash().ToString()
|
||||
);
|
||||
@ -123,39 +127,35 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
}
|
||||
else if (strCommand == NetMsgType::IXLOCKVOTE) //InstantX Lock Consensus Votes
|
||||
{
|
||||
CConsensusVote ctx;
|
||||
vRecv >> ctx;
|
||||
CConsensusVote vote;
|
||||
vRecv >> vote;
|
||||
|
||||
CInv inv(MSG_TXLOCK_VOTE, ctx.GetHash());
|
||||
CInv inv(MSG_TXLOCK_VOTE, vote.GetHash());
|
||||
pfrom->AddInventoryKnown(inv);
|
||||
|
||||
if(mapTxLockVote.count(ctx.GetHash())){
|
||||
return;
|
||||
}
|
||||
if(mapTxLockVote.count(vote.GetHash())) return;
|
||||
mapTxLockVote.insert(std::make_pair(vote.GetHash(), vote));
|
||||
|
||||
mapTxLockVote.insert(make_pair(ctx.GetHash(), ctx));
|
||||
|
||||
if(ProcessConsensusVote(pfrom, ctx)){
|
||||
if(ProcessConsensusVote(pfrom, vote)) {
|
||||
//Spam/Dos protection
|
||||
/*
|
||||
Masternodes will sometimes propagate votes before the transaction is known to the client.
|
||||
This tracks those messages and allows it at the same rate of the rest of the network, if
|
||||
a peer violates it, it will simply be ignored
|
||||
*/
|
||||
if(!mapTxLockReq.count(ctx.txHash) && !mapTxLockReqRejected.count(ctx.txHash)){
|
||||
if(!mapUnknownVotes.count(ctx.vinMasternode.prevout.hash)){
|
||||
mapUnknownVotes[ctx.vinMasternode.prevout.hash] = GetTime()+(60*10);
|
||||
}
|
||||
if(!mapTxLockReq.count(vote.txHash) && !mapTxLockReqRejected.count(vote.txHash)) {
|
||||
if(!mapUnknownVotes.count(vote.vinMasternode.prevout.hash))
|
||||
mapUnknownVotes[vote.vinMasternode.prevout.hash] = GetTime()+(60*10);
|
||||
|
||||
if(mapUnknownVotes[ctx.vinMasternode.prevout.hash] > GetTime() &&
|
||||
mapUnknownVotes[ctx.vinMasternode.prevout.hash] - GetAverageVoteTime() > 60*10){
|
||||
LogPrintf("ProcessMessageInstantX::ix - masternode is spamming transaction votes: %s %s\n",
|
||||
ctx.vinMasternode.ToString(),
|
||||
ctx.txHash.ToString()
|
||||
if(mapUnknownVotes[vote.vinMasternode.prevout.hash] > GetTime() &&
|
||||
mapUnknownVotes[vote.vinMasternode.prevout.hash] - GetAverageVoteTime() > 60*10) {
|
||||
LogPrintf("ProcessMessageInstantSend -- masternode is spamming transaction votes: %s %s\n",
|
||||
vote.vinMasternode.ToString(),
|
||||
vote.txHash.ToString()
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
mapUnknownVotes[ctx.vinMasternode.prevout.hash] = GetTime()+(60*10);
|
||||
mapUnknownVotes[vote.vinMasternode.prevout.hash] = GetTime()+(60*10);
|
||||
}
|
||||
}
|
||||
RelayInv(inv);
|
||||
@ -165,11 +165,12 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
}
|
||||
}
|
||||
|
||||
bool IsIXTXValid(const CTransaction& txCollateral){
|
||||
bool IsInstantSendTxValid(const CTransaction& txCollateral)
|
||||
{
|
||||
if(txCollateral.vout.size() < 1) return false;
|
||||
|
||||
if(!CheckFinalTx(txCollateral)) {
|
||||
LogPrint("instantsend", "IsIXTXValid - Transaction is not final - %s\n", txCollateral.ToString());
|
||||
LogPrint("instantsend", "IsInstantSendTxValid -- Transaction is not final: txCollateral=%s", txCollateral.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -177,28 +178,27 @@ bool IsIXTXValid(const CTransaction& txCollateral){
|
||||
int64_t nValueOut = 0;
|
||||
bool missingTx = false;
|
||||
|
||||
BOOST_FOREACH(const CTxOut o, txCollateral.vout)
|
||||
nValueOut += o.nValue;
|
||||
BOOST_FOREACH(const CTxOut txout, txCollateral.vout)
|
||||
nValueOut += txout.nValue;
|
||||
|
||||
BOOST_FOREACH(const CTxIn i, txCollateral.vin){
|
||||
BOOST_FOREACH(const CTxIn txin, txCollateral.vin) {
|
||||
CTransaction tx2;
|
||||
uint256 hash;
|
||||
if(GetTransaction(i.prevout.hash, tx2, Params().GetConsensus(), hash, true)){
|
||||
if(tx2.vout.size() > i.prevout.n) {
|
||||
nValueIn += tx2.vout[i.prevout.n].nValue;
|
||||
}
|
||||
} else{
|
||||
if(GetTransaction(txin.prevout.hash, tx2, Params().GetConsensus(), hash, true)) {
|
||||
if(tx2.vout.size() > txin.prevout.n)
|
||||
nValueIn += tx2.vout[txin.prevout.n].nValue;
|
||||
} else {
|
||||
missingTx = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(nValueOut > sporkManager.GetSporkValue(SPORK_5_MAX_VALUE)*COIN){
|
||||
LogPrint("instantsend", "IsIXTXValid -- Transaction value too high: nValueOut=%d, txCollateral=%s", nValueOut, txCollateral.ToString());
|
||||
if(nValueOut > sporkManager.GetSporkValue(SPORK_5_MAX_VALUE)*COIN) {
|
||||
LogPrint("instantsend", "IsInstantSendTxValid -- Transaction value too high: nValueOut=%d, txCollateral=%s", nValueOut, txCollateral.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(missingTx){
|
||||
LogPrint("instantsend", "IsIXTXValid - Unknown inputs in IX transaction - %s\n", txCollateral.ToString());
|
||||
if(missingTx) {
|
||||
LogPrint("instantsend", "IsInstantSendTxValid -- Unknown inputs in IX transaction: txCollateral=%s", txCollateral.ToString());
|
||||
/*
|
||||
This happens sometimes for an unknown reason, so we'll return that it's a valid transaction.
|
||||
If someone submits an invalid transaction it will be rejected by the network anyway and this isn't
|
||||
@ -208,7 +208,7 @@ bool IsIXTXValid(const CTransaction& txCollateral){
|
||||
}
|
||||
|
||||
if(nValueIn-nValueOut < INSTANTSEND_MIN_FEE) {
|
||||
LogPrint("instantsend", "IsIXTXValid - did not include enough fees in transaction %d\n%s\n", nValueOut-nValueIn, txCollateral.ToString());
|
||||
LogPrint("instantsend", "IsInstantSendTxValid -- did not include enough fees in transaction: fees=%d, txCollateral=%s", nValueOut-nValueIn, txCollateral.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -219,11 +219,10 @@ int64_t CreateNewLock(CTransaction tx)
|
||||
{
|
||||
|
||||
int64_t nTxAge = 0;
|
||||
BOOST_REVERSE_FOREACH(CTxIn i, tx.vin){
|
||||
nTxAge = GetInputAge(i);
|
||||
if(nTxAge < 5) //1 less than the "send IX" gui requires, incase of a block propagating the network at the time
|
||||
{
|
||||
LogPrintf("CreateNewLock - Transaction not found / too new: %d / %s\n", nTxAge, tx.GetHash().ToString());
|
||||
BOOST_REVERSE_FOREACH(CTxIn txin, tx.vin) {
|
||||
nTxAge = GetInputAge(txin);
|
||||
if(nTxAge < 5) { //1 less than the "send IX" gui requires, incase of a block propagating the network at the time
|
||||
LogPrintf("CreateNewLock -- Transaction not found / too new: nTxAge=%d, txid=%s\n", nTxAge, tx.GetHash().ToString());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -237,22 +236,24 @@ int64_t CreateNewLock(CTransaction tx)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
CBlockIndex* tip = chainActive.Tip();
|
||||
if(tip) nBlockHeight = tip->nHeight - nTxAge + 4;
|
||||
else return 0;
|
||||
if(tip)
|
||||
nBlockHeight = tip->nHeight - nTxAge + 4;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!mapTxLocks.count(tx.GetHash())){
|
||||
LogPrintf("CreateNewLock - New Transaction Lock %s !\n", tx.GetHash().ToString());
|
||||
if(!mapTxLocks.count(tx.GetHash())) {
|
||||
LogPrintf("CreateNewLock -- New Transaction Lock! txid=%s\n", tx.GetHash().ToString());
|
||||
|
||||
CTransactionLock newLock;
|
||||
newLock.nBlockHeight = nBlockHeight;
|
||||
newLock.nExpiration = GetTime()+(60*60); //locks expire after 60 minutes (24 confirmations)
|
||||
newLock.nTimeout = GetTime()+(60*5);
|
||||
newLock.txHash = tx.GetHash();
|
||||
mapTxLocks.insert(make_pair(tx.GetHash(), newLock));
|
||||
mapTxLocks.insert(std::make_pair(tx.GetHash(), newLock));
|
||||
} else {
|
||||
mapTxLocks[tx.GetHash()].nBlockHeight = nBlockHeight;
|
||||
LogPrint("instantsend", "CreateNewLock - Transaction Lock Exists %s !\n", tx.GetHash().ToString());
|
||||
LogPrint("instantsend", "CreateNewLock -- Transaction Lock Exists! txid=%s\n", tx.GetHash().ToString());
|
||||
}
|
||||
|
||||
|
||||
@ -265,110 +266,110 @@ void DoConsensusVote(CTransaction& tx, int64_t nBlockHeight)
|
||||
{
|
||||
if(!fMasterNode) return;
|
||||
|
||||
int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight, MIN_INSTANTX_PROTO_VERSION);
|
||||
int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight, MIN_INSTANTSEND_PROTO_VERSION);
|
||||
|
||||
if(n == -1)
|
||||
{
|
||||
LogPrint("instantsend", "InstantX::DoConsensusVote - Unknown Masternode %s\n", activeMasternode.vin.ToString());
|
||||
if(n == -1) {
|
||||
LogPrint("instantsend", "DoConsensusVote -- Unknown Masternode %s\n", activeMasternode.vin.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
if(n > INSTANTX_SIGNATURES_TOTAL)
|
||||
{
|
||||
LogPrint("instantsend", "InstantX::DoConsensusVote - Masternode not in the top %d (%d)\n", INSTANTX_SIGNATURES_TOTAL, n);
|
||||
if(n > INSTANTSEND_SIGNATURES_TOTAL) {
|
||||
LogPrint("instantsend", "DoConsensusVote -- Masternode not in the top %d (%d)\n", INSTANTSEND_SIGNATURES_TOTAL, n);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
nBlockHeight calculated from the transaction is the authoritive source
|
||||
*/
|
||||
|
||||
LogPrint("instantsend", "InstantX::DoConsensusVote - In the top %d (%d)\n", INSTANTX_SIGNATURES_TOTAL, n);
|
||||
LogPrint("instantsend", "DoConsensusVote -- In the top %d (%d)\n", INSTANTSEND_SIGNATURES_TOTAL, n);
|
||||
|
||||
CConsensusVote ctx;
|
||||
ctx.vinMasternode = activeMasternode.vin;
|
||||
ctx.txHash = tx.GetHash();
|
||||
ctx.nBlockHeight = nBlockHeight;
|
||||
if(!ctx.Sign()){
|
||||
LogPrintf("InstantX::DoConsensusVote - Failed to sign consensus vote\n");
|
||||
CConsensusVote vote;
|
||||
vote.vinMasternode = activeMasternode.vin;
|
||||
vote.txHash = tx.GetHash();
|
||||
vote.nBlockHeight = nBlockHeight;
|
||||
if(!vote.Sign()) {
|
||||
LogPrintf("DoConsensusVote -- Failed to sign consensus vote\n");
|
||||
return;
|
||||
}
|
||||
if(!ctx.SignatureValid()) {
|
||||
LogPrintf("InstantX::DoConsensusVote - Signature invalid\n");
|
||||
if(!vote.SignatureValid()) {
|
||||
LogPrintf("DoConsensusVote -- Signature invalid\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mapTxLockVote[ctx.GetHash()] = ctx;
|
||||
{
|
||||
LOCK(cs_instantsend);
|
||||
mapTxLockVote[vote.GetHash()] = vote;
|
||||
}
|
||||
|
||||
CInv inv(MSG_TXLOCK_VOTE, ctx.GetHash());
|
||||
CInv inv(MSG_TXLOCK_VOTE, vote.GetHash());
|
||||
RelayInv(inv);
|
||||
}
|
||||
|
||||
//received a consensus vote
|
||||
bool ProcessConsensusVote(CNode* pnode, CConsensusVote& ctx)
|
||||
bool ProcessConsensusVote(CNode* pnode, CConsensusVote& vote)
|
||||
{
|
||||
int n = mnodeman.GetMasternodeRank(ctx.vinMasternode, ctx.nBlockHeight, MIN_INSTANTX_PROTO_VERSION);
|
||||
int n = mnodeman.GetMasternodeRank(vote.vinMasternode, vote.nBlockHeight, MIN_INSTANTSEND_PROTO_VERSION);
|
||||
|
||||
CMasternode* pmn = mnodeman.Find(ctx.vinMasternode);
|
||||
CMasternode* pmn = mnodeman.Find(vote.vinMasternode);
|
||||
if(pmn != NULL)
|
||||
LogPrint("instantsend", "InstantX::ProcessConsensusVote - Masternode ADDR %s %d\n", pmn->addr.ToString(), n);
|
||||
LogPrint("instantsend", "ProcessConsensusVote -- Masternode addr=%s, rank: %d\n", pmn->addr.ToString(), n);
|
||||
|
||||
if(n == -1)
|
||||
{
|
||||
if(n == -1) {
|
||||
//can be caused by past versions trying to vote with an invalid protocol
|
||||
LogPrint("instantsend", "InstantX::ProcessConsensusVote - Unknown Masternode %s\n", ctx.vinMasternode.ToString());
|
||||
mnodeman.AskForMN(pnode, ctx.vinMasternode);
|
||||
LogPrint("instantsend", "ProcessConsensusVote -- Unknown Masternode: txin=%s\n", vote.vinMasternode.ToString());
|
||||
mnodeman.AskForMN(pnode, vote.vinMasternode);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(n > INSTANTX_SIGNATURES_TOTAL)
|
||||
{
|
||||
LogPrint("instantsend", "InstantX::ProcessConsensusVote - Masternode not in the top %d (%d) - %s\n", INSTANTX_SIGNATURES_TOTAL, n, ctx.GetHash().ToString());
|
||||
if(n > INSTANTSEND_SIGNATURES_TOTAL) {
|
||||
LogPrint("instantsend", "ProcessConsensusVote -- Masternode not in the top %d (%d): vote hash %s\n", INSTANTSEND_SIGNATURES_TOTAL, n, vote.GetHash().ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!ctx.SignatureValid()) {
|
||||
LogPrintf("InstantX::ProcessConsensusVote - Signature invalid\n");
|
||||
if(!vote.SignatureValid()) {
|
||||
LogPrintf("ProcessConsensusVote -- Signature invalid\n");
|
||||
// don't ban, it could just be a non-synced masternode
|
||||
mnodeman.AskForMN(pnode, ctx.vinMasternode);
|
||||
mnodeman.AskForMN(pnode, vote.vinMasternode);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mapTxLocks.count(ctx.txHash)){
|
||||
LogPrintf("InstantX::ProcessConsensusVote - New Transaction Lock %s !\n", ctx.txHash.ToString());
|
||||
if (!mapTxLocks.count(vote.txHash)) {
|
||||
LogPrintf("ProcessConsensusVote -- New Transaction Lock! txid=%s\n", vote.txHash.ToString());
|
||||
|
||||
CTransactionLock newLock;
|
||||
newLock.nBlockHeight = 0;
|
||||
newLock.nExpiration = GetTime()+(60*60);
|
||||
newLock.nTimeout = GetTime()+(60*5);
|
||||
newLock.txHash = ctx.txHash;
|
||||
mapTxLocks.insert(make_pair(ctx.txHash, newLock));
|
||||
} else
|
||||
LogPrint("instantsend", "InstantX::ProcessConsensusVote - Transaction Lock Exists %s !\n", ctx.txHash.ToString());
|
||||
newLock.txHash = vote.txHash;
|
||||
mapTxLocks.insert(std::make_pair(vote.txHash, newLock));
|
||||
} else {
|
||||
LogPrint("instantsend", "ProcessConsensusVote -- Transaction Lock Exists! txid=%s\n", vote.txHash.ToString());
|
||||
}
|
||||
|
||||
//compile consessus vote
|
||||
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(ctx.txHash);
|
||||
if (i != mapTxLocks.end()){
|
||||
(*i).second.AddSignature(ctx);
|
||||
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(vote.txHash);
|
||||
if (i != mapTxLocks.end()) {
|
||||
(*i).second.AddVote(vote);
|
||||
|
||||
int nSignatures = (*i).second.CountSignatures();
|
||||
LogPrint("instantsend", "InstantX::ProcessConsensusVote - Transaction Lock Votes %d - %s !\n", nSignatures, ctx.GetHash().ToString());
|
||||
int nSignatures = (*i).second.CountVotes();
|
||||
LogPrint("instantsend", "ProcessConsensusVote -- Transaction Lock signatures count: %d, vote hash=%s\n", nSignatures, vote.GetHash().ToString());
|
||||
|
||||
if(nSignatures >= INSTANTX_SIGNATURES_REQUIRED){
|
||||
LogPrint("instantsend", "InstantX::ProcessConsensusVote - Transaction Lock Is Complete %s !\n", ctx.txHash.ToString());
|
||||
if(nSignatures >= INSTANTSEND_SIGNATURES_REQUIRED) {
|
||||
LogPrint("instantsend", "ProcessConsensusVote -- Transaction Lock Is Complete! txid=%s\n", vote.txHash.ToString());
|
||||
|
||||
// Masternodes will sometimes propagate votes before the transaction is known to the client,
|
||||
// will check for conflicting locks and update transaction status on a new vote message
|
||||
// only after the lock itself has arrived
|
||||
if(!mapTxLockReq.count(ctx.txHash) && !mapTxLockReqRejected.count(ctx.txHash)) return true;
|
||||
if(!mapTxLockReq.count(vote.txHash) && !mapTxLockReqRejected.count(vote.txHash)) return true;
|
||||
|
||||
if(!FindConflictingLocks(mapTxLockReq[ctx.txHash])) { //?????
|
||||
if(mapTxLockReq.count(ctx.txHash)) {
|
||||
UpdateLockedTransaction(mapTxLockReq[ctx.txHash]);
|
||||
LockTransactionInputs(mapTxLockReq[ctx.txHash]);
|
||||
} else if(mapTxLockReqRejected.count(ctx.txHash)) {
|
||||
ResolveConflicts(mapTxLockReqRejected[ctx.txHash]); ///?????
|
||||
if(!FindConflictingLocks(mapTxLockReq[vote.txHash])) { //?????
|
||||
if(mapTxLockReq.count(vote.txHash)) {
|
||||
UpdateLockedTransaction(mapTxLockReq[vote.txHash]);
|
||||
LockTransactionInputs(mapTxLockReq[vote.txHash]);
|
||||
} else if(mapTxLockReqRejected.count(vote.txHash)) {
|
||||
ResolveConflicts(mapTxLockReqRejected[vote.txHash]); ///?????
|
||||
} else {
|
||||
LogPrint("instantsend", "InstantX::ProcessConsensusVote - Transaction Lock Request is missing %s ! votes %d\n", ctx.GetHash().ToString(), nSignatures);
|
||||
LogPrint("instantsend", "ProcessConsensusVote -- Transaction Lock Request is missing! nSignatures=%d, vote hash %s\n", nSignatures, vote.GetHash().ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -379,25 +380,25 @@ bool ProcessConsensusVote(CNode* pnode, CConsensusVote& ctx)
|
||||
return false;
|
||||
}
|
||||
|
||||
void UpdateLockedTransaction(CTransaction& tx, bool fForceNotification) {
|
||||
void UpdateLockedTransaction(CTransaction& tx, bool fForceNotification)
|
||||
{
|
||||
// there should be no conflicting locks
|
||||
if(FindConflictingLocks(tx)) return;
|
||||
uint256 txHash = tx.GetHash();
|
||||
// there must be a successfully verified lock request
|
||||
if (!mapTxLockReq.count(txHash)) return;
|
||||
if(!mapTxLockReq.count(txHash)) return;
|
||||
|
||||
int nSignatures = GetTransactionLockSignatures(txHash);
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
if(pwalletMain && pwalletMain->UpdatedTransaction(txHash)){
|
||||
if(pwalletMain && pwalletMain->UpdatedTransaction(txHash)) {
|
||||
// bumping this to update UI
|
||||
nCompleteTXLocks++;
|
||||
// a transaction lock must have enough signatures to trigger this notification
|
||||
if(nSignatures == INSTANTX_SIGNATURES_REQUIRED || (fForceNotification && nSignatures > INSTANTX_SIGNATURES_REQUIRED)) {
|
||||
if(nSignatures == INSTANTSEND_SIGNATURES_REQUIRED || (fForceNotification && nSignatures > INSTANTSEND_SIGNATURES_REQUIRED)) {
|
||||
// notify an external script once threshold is reached
|
||||
std::string strCmd = GetArg("-instantsendnotify", "");
|
||||
if ( !strCmd.empty())
|
||||
{
|
||||
if(!strCmd.empty()) {
|
||||
boost::replace_all(strCmd, "%s", txHash.GetHex());
|
||||
boost::thread t(runCommand, strCmd); // thread runs free
|
||||
}
|
||||
@ -405,19 +406,16 @@ void UpdateLockedTransaction(CTransaction& tx, bool fForceNotification) {
|
||||
}
|
||||
#endif
|
||||
|
||||
if(nSignatures == INSTANTX_SIGNATURES_REQUIRED || (fForceNotification && nSignatures > INSTANTX_SIGNATURES_REQUIRED)) {
|
||||
if(nSignatures == INSTANTSEND_SIGNATURES_REQUIRED || (fForceNotification && nSignatures > INSTANTSEND_SIGNATURES_REQUIRED))
|
||||
GetMainSignals().NotifyTransactionLock(tx);
|
||||
}
|
||||
}
|
||||
|
||||
void LockTransactionInputs(CTransaction& tx) {
|
||||
if(mapTxLockReq.count(tx.GetHash())){
|
||||
BOOST_FOREACH(const CTxIn& in, tx.vin){
|
||||
if(!mapLockedInputs.count(in.prevout)){
|
||||
mapLockedInputs.insert(make_pair(in.prevout, tx.GetHash()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!mapTxLockReq.count(tx.GetHash())) return;
|
||||
|
||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||
if(!mapLockedInputs.count(txin.prevout))
|
||||
mapLockedInputs.insert(std::make_pair(txin.prevout, tx.GetHash()));
|
||||
}
|
||||
|
||||
bool FindConflictingLocks(CTransaction& tx)
|
||||
@ -429,12 +427,17 @@ bool FindConflictingLocks(CTransaction& tx)
|
||||
Blocks could have been rejected during this time, which is OK. After they cancel out, the client will
|
||||
rescan the blocks and find they're acceptable and then take the chain with the most work.
|
||||
*/
|
||||
BOOST_FOREACH(const CTxIn& in, tx.vin){
|
||||
if(mapLockedInputs.count(in.prevout)){
|
||||
if(mapLockedInputs[in.prevout] != tx.GetHash()){
|
||||
LogPrintf("InstantX::FindConflictingLocks - found two complete conflicting locks - removing both. %s %s", tx.GetHash().ToString(), mapLockedInputs[in.prevout].ToString());
|
||||
if(mapTxLocks.count(tx.GetHash())) mapTxLocks[tx.GetHash()].nExpiration = GetTime();
|
||||
if(mapTxLocks.count(mapLockedInputs[in.prevout])) mapTxLocks[mapLockedInputs[in.prevout]].nExpiration = GetTime();
|
||||
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
|
||||
if(mapLockedInputs.count(txin.prevout)) {
|
||||
if(mapLockedInputs[txin.prevout] != tx.GetHash()) {
|
||||
LogPrintf("FindConflictingLocks -- found two complete conflicting locks, removing both: txid=%s, txin=%s", tx.GetHash().ToString(), mapLockedInputs[txin.prevout].ToString());
|
||||
|
||||
if(mapTxLocks.count(tx.GetHash()))
|
||||
mapTxLocks[tx.GetHash()].nExpiration = GetTime();
|
||||
|
||||
if(mapTxLocks.count(mapLockedInputs[txin.prevout]))
|
||||
mapTxLocks[mapLockedInputs[txin.prevout]].nExpiration = GetTime();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -443,14 +446,16 @@ bool FindConflictingLocks(CTransaction& tx)
|
||||
return false;
|
||||
}
|
||||
|
||||
void ResolveConflicts(CTransaction& tx) {
|
||||
void ResolveConflicts(CTransaction& tx)
|
||||
{
|
||||
// resolve conflicts
|
||||
if (IsLockedIXTransaction(tx.GetHash()) && !FindConflictingLocks(tx)){ //?????
|
||||
LogPrintf("ResolveConflicts - Found Existing Complete IX Lock, resolving...\n");
|
||||
if (IsLockedInstandSendTransaction(tx.GetHash()) && !FindConflictingLocks(tx)) { //?????
|
||||
LogPrintf("ResolveConflicts -- Found Existing Complete IX Lock, resolving...\n");
|
||||
|
||||
//reprocess the last 15 blocks
|
||||
ReprocessBlocks(15);
|
||||
if(!mapTxLockReq.count(tx.GetHash())) mapTxLockReq.insert(make_pair(tx.GetHash(), tx)); //?????
|
||||
if(!mapTxLockReq.count(tx.GetHash()))
|
||||
mapTxLockReq.insert(std::make_pair(tx.GetHash(), tx)); //?????
|
||||
}
|
||||
}
|
||||
|
||||
@ -471,23 +476,27 @@ int64_t GetAverageVoteTime()
|
||||
|
||||
void CleanTransactionLocksList()
|
||||
{
|
||||
LOCK(cs_instantsend);
|
||||
|
||||
std::map<uint256, CTransactionLock>::iterator it = mapTxLocks.begin();
|
||||
|
||||
while(it != mapTxLocks.end()) {
|
||||
if(GetTime() > it->second.nExpiration){ //keep them for an hour
|
||||
LogPrintf("Removing old transaction lock %s\n", it->second.txHash.ToString());
|
||||
CTransactionLock &txLock = it->second;
|
||||
if(GetTime() > txLock.nExpiration){
|
||||
LogPrintf("Removing old transaction lock: txid=%s\n", txLock.txHash.ToString());
|
||||
|
||||
if(mapTxLockReq.count(it->second.txHash)){
|
||||
CTransaction& tx = mapTxLockReq[it->second.txHash];
|
||||
if(mapTxLockReq.count(txLock.txHash)){
|
||||
CTransaction& tx = mapTxLockReq[txLock.txHash];
|
||||
|
||||
BOOST_FOREACH(const CTxIn& in, tx.vin)
|
||||
mapLockedInputs.erase(in.prevout);
|
||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||
mapLockedInputs.erase(txin.prevout);
|
||||
|
||||
mapTxLockReq.erase(it->second.txHash);
|
||||
mapTxLockReqRejected.erase(it->second.txHash);
|
||||
mapTxLockReq.erase(txLock.txHash);
|
||||
mapTxLockReqRejected.erase(txLock.txHash);
|
||||
|
||||
BOOST_FOREACH(CConsensusVote& v, it->second.vecConsensusVotes)
|
||||
mapTxLockVote.erase(v.GetHash());
|
||||
BOOST_FOREACH(const CConsensusVote& vote, txLock.vecConsensusVotes)
|
||||
if(mapTxLockVote.count(vote.GetHash()))
|
||||
mapTxLockVote.erase(vote.GetHash());
|
||||
}
|
||||
|
||||
mapTxLocks.erase(it++);
|
||||
@ -497,12 +506,13 @@ void CleanTransactionLocksList()
|
||||
}
|
||||
}
|
||||
|
||||
bool IsLockedIXTransaction(uint256 txHash) {
|
||||
bool IsLockedInstandSendTransaction(uint256 txHash)
|
||||
{
|
||||
// there must be a successfully verified lock request...
|
||||
if (!mapTxLockReq.count(txHash)) return false;
|
||||
// ...and corresponding lock must have enough signatures
|
||||
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(txHash);
|
||||
return i != mapTxLocks.end() && (*i).second.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED;
|
||||
return i != mapTxLocks.end() && (*i).second.CountVotes() >= INSTANTSEND_SIGNATURES_REQUIRED;
|
||||
}
|
||||
|
||||
int GetTransactionLockSignatures(uint256 txHash)
|
||||
@ -511,10 +521,8 @@ int GetTransactionLockSignatures(uint256 txHash)
|
||||
if(!sporkManager.IsSporkActive(SPORK_2_INSTANTX)) return -3;
|
||||
if(!fEnableInstantSend) return -1;
|
||||
|
||||
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(txHash);
|
||||
if (i != mapTxLocks.end()){
|
||||
return (*i).second.CountSignatures();
|
||||
}
|
||||
std::map<uint256, CTransactionLock>::iterator it = mapTxLocks.find(txHash);
|
||||
if(it != mapTxLocks.end()) return it->second.CountVotes();
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -524,9 +532,7 @@ bool IsTransactionLockTimedOut(uint256 txHash)
|
||||
if(!fEnableInstantSend) return 0;
|
||||
|
||||
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(txHash);
|
||||
if (i != mapTxLocks.end()){
|
||||
return GetTime() > (*i).second.nTimeout;
|
||||
}
|
||||
if (i != mapTxLocks.end()) return GetTime() > (*i).second.nTimeout;
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -545,14 +551,13 @@ bool CConsensusVote::SignatureValid()
|
||||
|
||||
CMasternode* pmn = mnodeman.Find(vinMasternode);
|
||||
|
||||
if(pmn == NULL)
|
||||
{
|
||||
LogPrintf("InstantX::CConsensusVote::SignatureValid() - Unknown Masternode %s\n", vinMasternode.ToString());
|
||||
if(pmn == NULL) {
|
||||
LogPrintf("CConsensusVote::SignatureValid -- Unknown Masternode: txin=%s\n", vinMasternode.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!darkSendSigner.VerifyMessage(pmn->pubkey2, vchMasterNodeSignature, strMessage, errorMessage)) {
|
||||
LogPrintf("InstantX::CConsensusVote::SignatureValid() - Verify message failed\n");
|
||||
LogPrintf("CConsensusVote::SignatureValid -- VerifyMessage() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -564,15 +569,14 @@ bool CConsensusVote::Sign()
|
||||
std::string errorMessage;
|
||||
|
||||
std::string strMessage = txHash.ToString().c_str() + boost::lexical_cast<std::string>(nBlockHeight);
|
||||
//LogPrintf("signing strMessage %s \n", strMessage);
|
||||
|
||||
if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, activeMasternode.keyMasternode)) {
|
||||
LogPrintf("CConsensusVote::Sign() - Sign message failed");
|
||||
LogPrintf("CConsensusVote::Sign -- SignMessage() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!darkSendSigner.VerifyMessage(activeMasternode.pubKeyMasternode, vchMasterNodeSignature, strMessage, errorMessage)) {
|
||||
LogPrintf("CConsensusVote::Sign() - Verify message failed");
|
||||
LogPrintf("CConsensusVote::Sign -- VerifyMessage() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -580,27 +584,25 @@ bool CConsensusVote::Sign()
|
||||
}
|
||||
|
||||
|
||||
bool CTransactionLock::SignaturesValid()
|
||||
bool CTransactionLock::VotesValid()
|
||||
{
|
||||
|
||||
BOOST_FOREACH(CConsensusVote vote, vecConsensusVotes)
|
||||
{
|
||||
int n = mnodeman.GetMasternodeRank(vote.vinMasternode, vote.nBlockHeight, MIN_INSTANTX_PROTO_VERSION);
|
||||
int n = mnodeman.GetMasternodeRank(vote.vinMasternode, vote.nBlockHeight, MIN_INSTANTSEND_PROTO_VERSION);
|
||||
|
||||
if(n == -1)
|
||||
{
|
||||
LogPrintf("CTransactionLock::SignaturesValid() - Unknown Masternode %s\n", vote.vinMasternode.ToString());
|
||||
if(n == -1) {
|
||||
LogPrintf("CTransactionLock::VotesValid -- Unknown Masternode, txin=%s\n", vote.vinMasternode.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(n > INSTANTX_SIGNATURES_TOTAL)
|
||||
{
|
||||
LogPrintf("CTransactionLock::SignaturesValid() - Masternode not in the top %s\n", INSTANTX_SIGNATURES_TOTAL);
|
||||
if(n > INSTANTSEND_SIGNATURES_TOTAL) {
|
||||
LogPrintf("CTransactionLock::VotesValid -- Masternode not in the top %s\n", INSTANTSEND_SIGNATURES_TOTAL);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!vote.SignatureValid()){
|
||||
LogPrintf("CTransactionLock::SignaturesValid() - Signature not valid\n");
|
||||
if(!vote.SignatureValid()) {
|
||||
LogPrintf("CTransactionLock::VotesValid -- Signature not valid\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -608,12 +610,12 @@ bool CTransactionLock::SignaturesValid()
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTransactionLock::AddSignature(CConsensusVote& cv)
|
||||
void CTransactionLock::AddVote(CConsensusVote& vote)
|
||||
{
|
||||
vecConsensusVotes.push_back(cv);
|
||||
vecConsensusVotes.push_back(vote);
|
||||
}
|
||||
|
||||
int CTransactionLock::CountSignatures()
|
||||
int CTransactionLock::CountVotes()
|
||||
{
|
||||
/*
|
||||
Only count signatures where the BlockHeight matches the transaction's blockheight.
|
||||
@ -622,11 +624,10 @@ int CTransactionLock::CountSignatures()
|
||||
|
||||
if(nBlockHeight == 0) return -1;
|
||||
|
||||
int n = 0;
|
||||
BOOST_FOREACH(CConsensusVote v, vecConsensusVotes){
|
||||
if(v.nBlockHeight == nBlockHeight){
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
int nCount = 0;
|
||||
BOOST_FOREACH(CConsensusVote vote, vecConsensusVotes)
|
||||
if(vote.nBlockHeight == nBlockHeight)
|
||||
nCount++;
|
||||
|
||||
return nCount;
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
|
||||
// Copyright (c) 2009-2012 The Dash Core developers
|
||||
// Copyright (c) 2009-2016 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.
|
||||
#ifndef INSTANTX_H
|
||||
@ -11,7 +10,10 @@
|
||||
#include "util.h"
|
||||
#include "base58.h"
|
||||
#include "main.h"
|
||||
#include "spork.h"
|
||||
|
||||
class CConsensusVote;
|
||||
class CTransaction;
|
||||
class CTransactionLock;
|
||||
|
||||
/*
|
||||
At 15 signatures, 1/2 of the masternode network can be owned by
|
||||
@ -22,37 +24,34 @@
|
||||
### getting 5 of 10 signatures w/ 1000 nodes of 2900
|
||||
(1000/2900.0)**5 = 0.004875397277841433
|
||||
*/
|
||||
#define INSTANTX_SIGNATURES_REQUIRED 6
|
||||
#define INSTANTX_SIGNATURES_TOTAL 10
|
||||
static const int INSTANTSEND_SIGNATURES_REQUIRED = 6;
|
||||
static const int INSTANTSEND_SIGNATURES_TOTAL = 10;
|
||||
static const int DEFAULT_INSTANTSEND_DEPTH = 5;
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
static const int MIN_INSTANTSEND_PROTO_VERSION = 70201;
|
||||
static const CAmount INSTANTSEND_MIN_FEE = 1 * CENT;
|
||||
|
||||
class CConsensusVote;
|
||||
class CTransaction;
|
||||
class CTransactionLock;
|
||||
|
||||
static const int MIN_INSTANTX_PROTO_VERSION = 70103;
|
||||
static const CAmount INSTANTSEND_MIN_FEE = 1 * CENT;
|
||||
|
||||
extern map<uint256, CTransaction> mapTxLockReq;
|
||||
extern map<uint256, CTransaction> mapTxLockReqRejected;
|
||||
extern map<uint256, CConsensusVote> mapTxLockVote;
|
||||
extern std::map<COutPoint, uint256> mapLockedInputs;
|
||||
extern bool fEnableInstantSend;
|
||||
extern int nInstantSendDepth;
|
||||
extern int nCompleteTXLocks;
|
||||
|
||||
extern std::map<uint256, CTransaction> mapTxLockReq;
|
||||
extern std::map<uint256, CTransaction> mapTxLockReqRejected;
|
||||
extern std::map<uint256, CConsensusVote> mapTxLockVote;
|
||||
extern std::map<COutPoint, uint256> mapLockedInputs;
|
||||
|
||||
|
||||
int64_t CreateNewLock(CTransaction tx);
|
||||
|
||||
bool IsIXTXValid(const CTransaction& txCollateral);
|
||||
bool IsInstantSendTxValid(const CTransaction& txCollateral);
|
||||
|
||||
void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
||||
void ProcessMessageInstantSend(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
||||
|
||||
//check if we need to vote on this transaction
|
||||
void DoConsensusVote(CTransaction& tx, int64_t nBlockHeight);
|
||||
|
||||
//process consensus vote message
|
||||
bool ProcessConsensusVote(CNode *pnode, CConsensusVote& ctx);
|
||||
bool ProcessConsensusVote(CNode *pnode, CConsensusVote& vote);
|
||||
|
||||
//update UI and notify external script if any
|
||||
void UpdateLockedTransaction(CTransaction& tx, bool fForceNotification = false);
|
||||
@ -69,7 +68,7 @@ void ResolveConflicts(CTransaction& tx);
|
||||
void CleanTransactionLocksList();
|
||||
|
||||
// verify if transaction is currently locked
|
||||
bool IsLockedIXTransaction(uint256 txHash);
|
||||
bool IsLockedInstandSendTransaction(uint256 txHash);
|
||||
|
||||
// get the actual uber og accepted lock signatures
|
||||
int GetTransactionLockSignatures(uint256 txHash);
|
||||
@ -112,9 +111,9 @@ public:
|
||||
int nExpiration;
|
||||
int nTimeout;
|
||||
|
||||
bool SignaturesValid();
|
||||
int CountSignatures();
|
||||
void AddSignature(CConsensusVote& cv);
|
||||
bool VotesValid();
|
||||
int CountVotes();
|
||||
void AddVote(CConsensusVote& vote);
|
||||
|
||||
uint256 GetHash()
|
||||
{
|
||||
|
41
src/main.cpp
41
src/main.cpp
@ -962,7 +962,7 @@ int GetInputAgeIX(uint256 nTXHash, CTxIn& vin)
|
||||
int nResult = GetInputAge(vin);
|
||||
if(nResult < 0) return -1;
|
||||
|
||||
if (nResult < 6 && IsLockedIXTransaction(nTXHash))
|
||||
if (nResult < 6 && IsLockedInstandSendTransaction(nTXHash))
|
||||
return nInstantSendDepth + nResult;
|
||||
|
||||
return nResult;
|
||||
@ -970,7 +970,7 @@ int GetInputAgeIX(uint256 nTXHash, CTxIn& vin)
|
||||
|
||||
int GetIXConfirmations(uint256 nTXHash)
|
||||
{
|
||||
if (IsLockedIXTransaction(nTXHash))
|
||||
if (IsLockedInstandSendTransaction(nTXHash))
|
||||
return nInstantSendDepth;
|
||||
|
||||
return 0;
|
||||
@ -4887,12 +4887,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
||||
if(mapDarksendBroadcastTxes.count(inv.hash)) {
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss.reserve(1000);
|
||||
ss <<
|
||||
mapDarksendBroadcastTxes[inv.hash].tx <<
|
||||
mapDarksendBroadcastTxes[inv.hash].vin <<
|
||||
mapDarksendBroadcastTxes[inv.hash].vchSig <<
|
||||
mapDarksendBroadcastTxes[inv.hash].sigTime;
|
||||
|
||||
ss << mapDarksendBroadcastTxes[inv.hash];
|
||||
pfrom->PushMessage(NetMsgType::DSTX, ss);
|
||||
pushed = true;
|
||||
}
|
||||
@ -5401,46 +5396,30 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
vector<uint256> vEraseQueue;
|
||||
CTransaction tx;
|
||||
|
||||
//masternode signed transaction
|
||||
CTxIn vin;
|
||||
vector<unsigned char> vchSig;
|
||||
int64_t sigTime;
|
||||
|
||||
if(strCommand == NetMsgType::TX) {
|
||||
vRecv >> tx;
|
||||
} else if (strCommand == NetMsgType::DSTX) {
|
||||
//these allow masternodes to publish a limited amount of free transactions
|
||||
vRecv >> tx >> vin >> vchSig >> sigTime;
|
||||
CDarksendBroadcastTx dstx;
|
||||
vRecv >> dstx;
|
||||
tx = dstx.tx;
|
||||
|
||||
CMasternode* pmn = mnodeman.Find(vin);
|
||||
CMasternode* pmn = mnodeman.Find(dstx.vin);
|
||||
if(pmn != NULL)
|
||||
{
|
||||
if(!pmn->allowFreeTx){
|
||||
//multiple peers can send us a valid masternode transaction
|
||||
if(fDebug) LogPrintf("dstx: Masternode sending too many transactions %s\n", tx.GetHash().ToString());
|
||||
LogPrint("privatesend", "dstx: Masternode sending too many transactions %s\n", tx.GetHash().ToString());
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string strMessage = tx.GetHash().ToString() + boost::lexical_cast<std::string>(sigTime);
|
||||
|
||||
std::string errorMessage = "";
|
||||
if(!darkSendSigner.VerifyMessage(pmn->pubkey2, vchSig, strMessage, errorMessage)){
|
||||
LogPrintf("dstx: Got bad Masternode transaction signature %s\n", vin.ToString());
|
||||
//pfrom->Misbehaving(20);
|
||||
return false;
|
||||
}
|
||||
if(!dstx.CheckSignature()) return false;
|
||||
|
||||
LogPrintf("dstx: Got Masternode transaction %s\n", tx.GetHash().ToString());
|
||||
|
||||
pmn->allowFreeTx = false;
|
||||
|
||||
if(!mapDarksendBroadcastTxes.count(tx.GetHash())){
|
||||
CDarksendBroadcastTx dstx;
|
||||
dstx.tx = tx;
|
||||
dstx.vin = vin;
|
||||
dstx.vchSig = vchSig;
|
||||
dstx.sigTime = sigTime;
|
||||
|
||||
mapDarksendBroadcastTxes.insert(make_pair(tx.GetHash(), dstx));
|
||||
}
|
||||
}
|
||||
@ -5947,7 +5926,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
darkSendPool.ProcessMessage(pfrom, strCommand, vRecv);
|
||||
mnodeman.ProcessMessage(pfrom, strCommand, vRecv);
|
||||
mnpayments.ProcessMessage(pfrom, strCommand, vRecv);
|
||||
ProcessMessageInstantX(pfrom, strCommand, vRecv);
|
||||
ProcessMessageInstantSend(pfrom, strCommand, vRecv);
|
||||
sporkManager.ProcessSpork(pfrom, strCommand, vRecv);
|
||||
masternodeSync.ProcessMessage(pfrom, strCommand, vRecv);
|
||||
governance.ProcessMessage(pfrom, strCommand, vRecv);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "masternode-sync.h"
|
||||
#include "masternodeman.h"
|
||||
#include "darksend.h"
|
||||
#include "activemasternode.h"
|
||||
#include "util.h"
|
||||
#include "sync.h"
|
||||
#include "spork.h"
|
||||
|
@ -150,7 +150,7 @@ void CMasternodeSync::GetNextAsset()
|
||||
RequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED;
|
||||
uiInterface.NotifyAdditionalDataSyncProgressChanged(1);
|
||||
//try to activate our masternode if possible
|
||||
activeMasternode.ManageStatus();
|
||||
activeMasternode.ManageState();
|
||||
break;
|
||||
}
|
||||
RequestedMasternodeAttempt = 0;
|
||||
@ -402,7 +402,6 @@ void CMasternodeSync::Process()
|
||||
// }
|
||||
// }
|
||||
|
||||
if (pnode->nVersion < MSG_GOVERNANCE_PEER_PROTO_VERSION) continue;
|
||||
|
||||
// only request once from each peer
|
||||
if(pnode->HasFulfilledRequest("governance-sync")) continue;
|
||||
|
@ -3,7 +3,9 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "consensus/validation.h"
|
||||
#include "activemasternode.h"
|
||||
#include "darksend.h"
|
||||
#include "init.h"
|
||||
#include "masternode.h"
|
||||
#include "masternode-payments.h"
|
||||
#include "masternode-sync.h"
|
||||
@ -369,7 +371,7 @@ bool CMasternodeBroadcast::Create(std::string strService, std::string strKeyMast
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!darkSendSigner.SetKey(strKeyMasternode, strErrorMessage, keyMasternodeNew, pubKeyMasternodeNew)) {
|
||||
if(!darkSendSigner.GetKeysFromSecret(strKeyMasternode, strErrorMessage, keyMasternodeNew, pubKeyMasternodeNew)) {
|
||||
strErrorMessage = strprintf("Can't find keys for masternode %s, error: %s", strService, strErrorMessage);
|
||||
LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorMessage);
|
||||
return false;
|
||||
|
@ -394,7 +394,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fConnectToMas
|
||||
{
|
||||
if (pszDest == NULL) {
|
||||
// we clean masternode connections in CMasternodeMan::ProcessMasternodeConnections()
|
||||
// so should be safe to skip this and connect to local Hot MN on CActiveMasternode::ManageStatus()
|
||||
// so should be safe to skip this and connect to local Hot MN on CActiveMasternode::ManageState()
|
||||
if (IsLocal(addrConnect) && !fConnectToMasternode)
|
||||
return NULL;
|
||||
|
||||
@ -2077,11 +2077,7 @@ void RelayTransaction(const CTransaction& tx)
|
||||
ss.reserve(10000);
|
||||
uint256 hash = tx.GetHash();
|
||||
if(mapDarksendBroadcastTxes.count(hash)) { // MSG_DSTX
|
||||
ss <<
|
||||
mapDarksendBroadcastTxes[hash].tx <<
|
||||
mapDarksendBroadcastTxes[hash].vin <<
|
||||
mapDarksendBroadcastTxes[hash].vchSig <<
|
||||
mapDarksendBroadcastTxes[hash].sigTime;
|
||||
ss << mapDarksendBroadcastTxes[hash];
|
||||
} else if(mapTxLockReq.count(hash)) { // MSG_TXLOCK_REQUEST
|
||||
ss << mapTxLockReq[hash];
|
||||
} else { // MSG_TX
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "chainparams.h"
|
||||
#include "checkpoints.h"
|
||||
#include "clientversion.h"
|
||||
#include "darksend.h"
|
||||
#include "net.h"
|
||||
#include "txmempool.h"
|
||||
#include "ui_interface.h"
|
||||
@ -74,7 +75,7 @@ int ClientModel::getNumConnections(unsigned int flags) const
|
||||
QString ClientModel::getMasternodeCountString() const
|
||||
{
|
||||
return tr("Total: %1 (PS compatible: %2 / Enabled: %3)").arg(QString::number((int)mnodeman.size()))
|
||||
.arg(QString::number((int)mnodeman.CountEnabled(MIN_POOL_PEER_PROTO_VERSION)))
|
||||
.arg(QString::number((int)mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION)))
|
||||
.arg(QString::number((int)mnodeman.CountEnabled()));
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,10 @@
|
||||
#include "ui_darksendconfig.h"
|
||||
|
||||
#include "bitcoinunits.h"
|
||||
#include "darksend.h"
|
||||
#include "guiconstants.h"
|
||||
#include "optionsmodel.h"
|
||||
#include "walletmodel.h"
|
||||
#include "init.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
|
@ -661,7 +661,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
/// 7a. parse masternode.conf
|
||||
string strErr;
|
||||
std::string strErr;
|
||||
if(!masternodeConfig.read(strErr)) {
|
||||
QMessageBox::critical(0, QObject::tr("Dash Core"),
|
||||
QObject::tr("Error reading masternode configuration file: %1").arg(strErr.c_str()));
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include <QMessageBox>
|
||||
#include <QTimer>
|
||||
|
||||
extern CWallet* pwalletMain;
|
||||
|
||||
OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::OptionsDialog),
|
||||
@ -257,7 +259,7 @@ void OptionsDialog::on_resetButton_clicked()
|
||||
void OptionsDialog::on_okButton_clicked()
|
||||
{
|
||||
mapper->submit();
|
||||
darkSendPool.cachedNumBlocks = std::numeric_limits<int>::max();
|
||||
darkSendPool.nCachedNumBlocks = std::numeric_limits<int>::max();
|
||||
pwalletMain->MarkDirty();
|
||||
accept();
|
||||
updateDefaultProxyNets();
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "guiutil.h"
|
||||
|
||||
#include "amount.h"
|
||||
#include "darksend.h"
|
||||
#include "init.h"
|
||||
#include "main.h" // For DEFAULT_SCRIPTCHECK_THREADS
|
||||
#include "net.h"
|
||||
@ -119,7 +120,7 @@ void OptionsModel::Init(bool resetSettings)
|
||||
|
||||
// PrivateSend
|
||||
if (!settings.contains("nPrivateSendRounds"))
|
||||
settings.setValue("nPrivateSendRounds", 2);
|
||||
settings.setValue("nPrivateSendRounds", DEFAULT_PRIVATESEND_ROUNDS);
|
||||
if (!SoftSetArg("-privatesendrounds", settings.value("nPrivateSendRounds").toString().toStdString()))
|
||||
addOverriddenOption("-privatesendrounds");
|
||||
nPrivateSendRounds = settings.value("nPrivateSendRounds").toInt();
|
||||
@ -127,7 +128,7 @@ void OptionsModel::Init(bool resetSettings)
|
||||
if (!settings.contains("nPrivateSendAmount")) {
|
||||
// for migration from old settings
|
||||
if (!settings.contains("nAnonymizeDashAmount"))
|
||||
settings.setValue("nPrivateSendAmount", 1000);
|
||||
settings.setValue("nPrivateSendAmount", DEFAULT_PRIVATESEND_AMOUNT);
|
||||
else
|
||||
settings.setValue("nPrivateSendAmount", settings.value("nAnonymizeDashAmount").toInt());
|
||||
}
|
||||
@ -136,7 +137,7 @@ void OptionsModel::Init(bool resetSettings)
|
||||
nPrivateSendAmount = settings.value("nPrivateSendAmount").toInt();
|
||||
|
||||
if (!settings.contains("fPrivateSendMultiSession"))
|
||||
settings.setValue("fPrivateSendMultiSession", fPrivateSendMultiSession);
|
||||
settings.setValue("fPrivateSendMultiSession", DEFAULT_PRIVATESEND_MULTISESSION);
|
||||
if (!SoftSetBoolArg("-privatesendmultisession", settings.value("fPrivateSendMultiSession").toBool()))
|
||||
addOverriddenOption("-privatesendmultisession");
|
||||
fPrivateSendMultiSession = settings.value("fPrivateSendMultiSession").toBool();
|
||||
|
@ -452,17 +452,17 @@ void OverviewPage::privateSendStatus()
|
||||
int nBestHeight = clientModel->getNumBlocks();
|
||||
|
||||
// We are processing more then 1 block per second, we'll just leave
|
||||
if(((nBestHeight - darkSendPool.cachedNumBlocks) / (GetTimeMillis() - nLastDSProgressBlockTime + 1) > 1)) return;
|
||||
if(((nBestHeight - darkSendPool.nCachedNumBlocks) / (GetTimeMillis() - nLastDSProgressBlockTime + 1) > 1)) return;
|
||||
nLastDSProgressBlockTime = GetTimeMillis();
|
||||
|
||||
QString strKeysLeftText(tr("keys left: %1").arg(pwalletMain->nKeysLeftSinceAutoBackup));
|
||||
if(pwalletMain->nKeysLeftSinceAutoBackup < PS_KEYS_THRESHOLD_WARNING) {
|
||||
if(pwalletMain->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING) {
|
||||
strKeysLeftText = "<span style='color:red;'>" + strKeysLeftText + "</span>";
|
||||
}
|
||||
ui->labelPrivateSendEnabled->setToolTip(strKeysLeftText);
|
||||
|
||||
// Warn user that wallet is running out of keys
|
||||
if (nWalletBackups > 0 && pwalletMain->nKeysLeftSinceAutoBackup < PS_KEYS_THRESHOLD_WARNING) {
|
||||
if (nWalletBackups > 0 && pwalletMain->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING) {
|
||||
QSettings settings;
|
||||
if(settings.value("fLowKeysWarning").toBool()) {
|
||||
QString strWarn = tr("Very low number of keys left since last automatic backup!") + "<br><br>" +
|
||||
@ -521,8 +521,8 @@ void OverviewPage::privateSendStatus()
|
||||
}
|
||||
|
||||
if(!fEnablePrivateSend) {
|
||||
if(nBestHeight != darkSendPool.cachedNumBlocks) {
|
||||
darkSendPool.cachedNumBlocks = nBestHeight;
|
||||
if(nBestHeight != darkSendPool.nCachedNumBlocks) {
|
||||
darkSendPool.nCachedNumBlocks = nBestHeight;
|
||||
updatePrivateSendProgress();
|
||||
}
|
||||
|
||||
@ -533,9 +533,9 @@ void OverviewPage::privateSendStatus()
|
||||
}
|
||||
|
||||
// check darksend status and unlock if needed
|
||||
if(nBestHeight != darkSendPool.cachedNumBlocks) {
|
||||
if(nBestHeight != darkSendPool.nCachedNumBlocks) {
|
||||
// Balance and number of transactions might have changed
|
||||
darkSendPool.cachedNumBlocks = nBestHeight;
|
||||
darkSendPool.nCachedNumBlocks = nBestHeight;
|
||||
updatePrivateSendProgress();
|
||||
}
|
||||
|
||||
@ -548,13 +548,11 @@ void OverviewPage::privateSendStatus()
|
||||
|
||||
ui->labelPrivateSendLastMessage->setText(s);
|
||||
|
||||
if(darkSendPool.sessionDenom == 0){
|
||||
if(darkSendPool.nSessionDenom == 0){
|
||||
ui->labelSubmittedDenom->setText(tr("N/A"));
|
||||
} else {
|
||||
std::string out;
|
||||
darkSendPool.GetDenominationsToString(darkSendPool.sessionDenom, out);
|
||||
QString s2(out.c_str());
|
||||
ui->labelSubmittedDenom->setText(s2);
|
||||
QString strDenom(darkSendPool.GetDenominationsToString(darkSendPool.nSessionDenom).c_str());
|
||||
ui->labelSubmittedDenom->setText(strDenom);
|
||||
}
|
||||
|
||||
}
|
||||
@ -564,7 +562,7 @@ void OverviewPage::privateSendAuto(){
|
||||
}
|
||||
|
||||
void OverviewPage::privateSendReset(){
|
||||
darkSendPool.Reset();
|
||||
darkSendPool.ResetPool();
|
||||
|
||||
QMessageBox::warning(this, tr("PrivateSend"),
|
||||
tr("PrivateSend was successfully reset."),
|
||||
@ -599,7 +597,7 @@ void OverviewPage::togglePrivateSend(){
|
||||
if(!ctx.isValid())
|
||||
{
|
||||
//unlock was cancelled
|
||||
darkSendPool.cachedNumBlocks = std::numeric_limits<int>::max();
|
||||
darkSendPool.nCachedNumBlocks = std::numeric_limits<int>::max();
|
||||
QMessageBox::warning(this, tr("PrivateSend"),
|
||||
tr("Wallet is locked and user declined to unlock. Disabling PrivateSend."),
|
||||
QMessageBox::Ok, QMessageBox::Ok);
|
||||
@ -611,7 +609,7 @@ void OverviewPage::togglePrivateSend(){
|
||||
}
|
||||
|
||||
fEnablePrivateSend = !fEnablePrivateSend;
|
||||
darkSendPool.cachedNumBlocks = std::numeric_limits<int>::max();
|
||||
darkSendPool.nCachedNumBlocks = std::numeric_limits<int>::max();
|
||||
|
||||
if(!fEnablePrivateSend){
|
||||
ui->togglePrivateSend->setText(tr("Start Mixing"));
|
||||
|
@ -38,7 +38,7 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
|
||||
QString strUsingIX = "";
|
||||
if(signatures >= 0){
|
||||
|
||||
if(signatures >= INSTANTX_SIGNATURES_REQUIRED){
|
||||
if(signatures >= INSTANTSEND_SIGNATURES_REQUIRED){
|
||||
int nDepth = wtx.GetDepthInMainChain();
|
||||
if (nDepth < 0)
|
||||
return tr("conflicted");
|
||||
@ -54,11 +54,11 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
|
||||
if (nDepth < 0)
|
||||
return tr("conflicted");
|
||||
else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
|
||||
return tr("%1/offline (InstantSend verification in progress - %2 of %3 signatures)").arg(nDepth).arg(signatures).arg(INSTANTX_SIGNATURES_TOTAL);
|
||||
return tr("%1/offline (InstantSend verification in progress - %2 of %3 signatures)").arg(nDepth).arg(signatures).arg(INSTANTSEND_SIGNATURES_TOTAL);
|
||||
else if (nDepth < 6)
|
||||
return tr("%1/confirmed (InstantSend verification in progress - %2 of %3 signatures )").arg(nDepth).arg(signatures).arg(INSTANTX_SIGNATURES_TOTAL);
|
||||
return tr("%1/confirmed (InstantSend verification in progress - %2 of %3 signatures )").arg(nDepth).arg(signatures).arg(INSTANTSEND_SIGNATURES_TOTAL);
|
||||
else
|
||||
return tr("%1 confirmations (InstantSend verification in progress - %2 of %3 signatures)").arg(nDepth).arg(signatures).arg(INSTANTX_SIGNATURES_TOTAL);
|
||||
return tr("%1 confirmations (InstantSend verification in progress - %2 of %3 signatures)").arg(nDepth).arg(signatures).arg(INSTANTSEND_SIGNATURES_TOTAL);
|
||||
} else {
|
||||
int nDepth = wtx.GetDepthInMainChain();
|
||||
if (nDepth < 0)
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "transactiontablemodel.h"
|
||||
|
||||
#include "base58.h"
|
||||
#include "darksend.h"
|
||||
#include "keystore.h"
|
||||
#include "main.h"
|
||||
#include "sync.h"
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "db.h"
|
||||
#include "init.h"
|
||||
#include "activemasternode.h"
|
||||
#include "darksend.h"
|
||||
#include "governance.h"
|
||||
#include "masternode-payments.h"
|
||||
#include "masternode-sync.h"
|
||||
@ -234,7 +235,7 @@ UniValue mngovernance(const UniValue& params, bool fHelp)
|
||||
|
||||
UniValue statusObj(UniValue::VOBJ);
|
||||
|
||||
if(!darkSendSigner.SetKey(mne.getPrivKey(), errorMessage, keyMasternode, pubKeyMasternode)){
|
||||
if(!darkSendSigner.GetKeysFromSecret(mne.getPrivKey(), errorMessage, keyMasternode, pubKeyMasternode)){
|
||||
failed++;
|
||||
statusObj.push_back(Pair("result", "failed"));
|
||||
statusObj.push_back(Pair("errorMessage", "Masternode signing error, could not set key correctly: " + errorMessage));
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "db.h"
|
||||
#include "init.h"
|
||||
#include "activemasternode.h"
|
||||
#include "darksend.h"
|
||||
#include "governance.h"
|
||||
#include "masternode-payments.h"
|
||||
#include "masternode-sync.h"
|
||||
@ -51,7 +52,7 @@ UniValue privatesend(const UniValue& params, bool fHelp)
|
||||
}
|
||||
|
||||
if(params[0].get_str() == "reset"){
|
||||
darkSendPool.Reset();
|
||||
darkSendPool.ResetPool();
|
||||
return "Mixing was reset";
|
||||
}
|
||||
|
||||
@ -59,7 +60,7 @@ UniValue privatesend(const UniValue& params, bool fHelp)
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.push_back(Pair("status", darkSendPool.GetStatus()));
|
||||
obj.push_back(Pair("keys_left", pwalletMain->nKeysLeftSinceAutoBackup));
|
||||
obj.push_back(Pair("warnings", (pwalletMain->nKeysLeftSinceAutoBackup < PS_KEYS_THRESHOLD_WARNING
|
||||
obj.push_back(Pair("warnings", (pwalletMain->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING
|
||||
? "WARNING: keypool is almost depleted!" : "")));
|
||||
return obj;
|
||||
}
|
||||
@ -77,7 +78,7 @@ UniValue getpoolinfo(const UniValue& params, bool fHelp)
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
if (darkSendPool.pSubmittedToMasternode)
|
||||
obj.push_back(Pair("masternode", darkSendPool.pSubmittedToMasternode->addr.ToString()));
|
||||
obj.push_back(Pair("queue", (int64_t)vecDarksendQueue.size()));
|
||||
obj.push_back(Pair("queue", darkSendPool.GetQueueSize()));
|
||||
obj.push_back(Pair("state", darkSendPool.GetState()));
|
||||
obj.push_back(Pair("entries", darkSendPool.GetEntriesCount()));
|
||||
obj.push_back(Pair("entries_accepted", darkSendPool.GetCountEntriesAccepted()));
|
||||
@ -161,12 +162,12 @@ UniValue masternode(const UniValue& params, bool fHelp)
|
||||
mnodeman.GetNextMasternodeInQueueForPayment(chainActive.Tip()->nHeight, true, nCount);
|
||||
}
|
||||
|
||||
if(params[1].get_str() == "ps") return mnodeman.CountEnabled(MIN_POOL_PEER_PROTO_VERSION);
|
||||
if(params[1].get_str() == "ps") return mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION);
|
||||
if(params[1].get_str() == "enabled") return mnodeman.CountEnabled();
|
||||
if(params[1].get_str() == "qualify") return nCount;
|
||||
if(params[1].get_str() == "all") return strprintf("Total: %d (PS Compatible: %d / Enabled: %d / Qualify: %d)",
|
||||
mnodeman.size(),
|
||||
mnodeman.CountEnabled(MIN_POOL_PEER_PROTO_VERSION),
|
||||
mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION),
|
||||
mnodeman.CountEnabled(),
|
||||
nCount);
|
||||
}
|
||||
@ -199,7 +200,7 @@ UniValue masternode(const UniValue& params, bool fHelp)
|
||||
|
||||
if (strCommand == "debug")
|
||||
{
|
||||
if(activeMasternode.status != ACTIVE_MASTERNODE_INITIAL || !masternodeSync.IsBlockchainSynced())
|
||||
if(activeMasternode.nState != ACTIVE_MASTERNODE_INITIAL || !masternodeSync.IsBlockchainSynced())
|
||||
return activeMasternode.GetStatus();
|
||||
|
||||
CTxIn vin = CTxIn();
|
||||
@ -236,9 +237,9 @@ UniValue masternode(const UniValue& params, bool fHelp)
|
||||
}
|
||||
}
|
||||
|
||||
if(activeMasternode.status != ACTIVE_MASTERNODE_STARTED){
|
||||
activeMasternode.status = ACTIVE_MASTERNODE_INITIAL; // TODO: consider better way
|
||||
activeMasternode.ManageStatus();
|
||||
if(activeMasternode.nState != ACTIVE_MASTERNODE_STARTED){
|
||||
activeMasternode.nState = ACTIVE_MASTERNODE_INITIAL; // TODO: consider better way
|
||||
activeMasternode.ManageState();
|
||||
pwalletMain->Lock();
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ bool CSporkMessage::Sign(std::string strSignKey)
|
||||
CPubKey pubkey;
|
||||
std::string errorMessage = "";
|
||||
|
||||
if(!darkSendSigner.SetKey(strSignKey, errorMessage, key, pubkey)) {
|
||||
if(!darkSendSigner.GetKeysFromSecret(strSignKey, errorMessage, key, pubkey)) {
|
||||
LogPrintf("CSporkMessage::Sign -- ERROR: '%s'\n", errorMessage);
|
||||
return false;
|
||||
}
|
||||
|
10
src/util.cpp
10
src/util.cpp
@ -104,13 +104,7 @@ using namespace std;
|
||||
|
||||
//Dash only features
|
||||
bool fMasterNode = false;
|
||||
string strMasterNodeAddr = "";
|
||||
bool fLiteMode = false;
|
||||
bool fEnableInstantSend = true;
|
||||
int nInstantSendDepth = 5;
|
||||
int nPrivateSendRounds = 2;
|
||||
int nPrivateSendAmount = 1000;
|
||||
int nLiquidityProvider = 0;
|
||||
/**
|
||||
nWalletBackups:
|
||||
1..10 - number of automatic backups to keep
|
||||
@ -122,10 +116,6 @@ int nWalletBackups = 10;
|
||||
/** Spork enforcement enabled time */
|
||||
int64_t enforceMasternodePaymentsTime = 4085657524;
|
||||
bool fSucessfullyLoaded = false;
|
||||
bool fEnablePrivateSend = false;
|
||||
bool fPrivateSendMultiSession = false;
|
||||
/** All denominations used by darksend */
|
||||
std::vector<CAmount> darkSendDenominations;
|
||||
string strBudgetMode = "";
|
||||
|
||||
const char * const BITCOIN_CONF_FILENAME = "dash.conf";
|
||||
|
@ -34,19 +34,10 @@
|
||||
|
||||
extern bool fMasterNode;
|
||||
extern bool fLiteMode;
|
||||
extern bool fEnableInstantSend;
|
||||
extern int nInstantSendDepth;
|
||||
extern int nPrivateSendRounds;
|
||||
extern int nPrivateSendAmount;
|
||||
extern int nLiquidityProvider;
|
||||
extern int nWalletBackups;
|
||||
extern bool fEnablePrivateSend;
|
||||
extern bool fPrivateSendMultiSession;
|
||||
extern int64_t enforceMasternodePaymentsTime;
|
||||
extern std::string strMasterNodeAddr;
|
||||
extern int keysLoaded;
|
||||
extern bool fSucessfullyLoaded;
|
||||
extern std::vector<CAmount> darkSendDenominations;
|
||||
extern std::string strBudgetMode;
|
||||
|
||||
static const bool DEFAULT_LOGTIMEMICROS = false;
|
||||
|
@ -21,9 +21,6 @@ static const int GETHEADERS_VERSION = 70077;
|
||||
//! disconnect from peers older than this proto version
|
||||
static const int MIN_PEER_PROTO_VERSION = 70103;
|
||||
|
||||
//! minimum peer version accepted by DarksendPool
|
||||
static const int MIN_POOL_PEER_PROTO_VERSION = 70201;
|
||||
|
||||
//! minimum peer version for masternode budgets
|
||||
static const int MSG_GOVERNANCE_PEER_PROTO_VERSION = 70201;
|
||||
|
||||
|
@ -82,7 +82,7 @@ std::string COutput::ToString() const
|
||||
|
||||
int COutput::Priority() const
|
||||
{
|
||||
BOOST_FOREACH(CAmount d, darkSendDenominations)
|
||||
BOOST_FOREACH(CAmount d, vecPrivateSendDenominations)
|
||||
if(tx->vout[i].nValue == d) return 10000;
|
||||
if(tx->vout[i].nValue < 1*COIN) return 20000;
|
||||
|
||||
@ -1175,7 +1175,7 @@ bool CWallet::IsDenominated(const CTransaction& tx) const
|
||||
|
||||
bool CWallet::IsDenominatedAmount(CAmount nInputAmount) const
|
||||
{
|
||||
BOOST_FOREACH(CAmount d, darkSendDenominations)
|
||||
BOOST_FOREACH(CAmount d, vecPrivateSendDenominations)
|
||||
if(nInputAmount == d)
|
||||
return true;
|
||||
return false;
|
||||
@ -1896,7 +1896,7 @@ CAmount CWallet::GetAnonymizableBalance() const
|
||||
|
||||
BOOST_FOREACH(CompactTallyItem& item, vecTally) {
|
||||
// try to anonymize all denoms and anything greater than sum of 10 smallest denoms
|
||||
if(IsDenominatedAmount(item.nAmount) || item.nAmount >= darkSendDenominations.back() * 10)
|
||||
if(IsDenominatedAmount(item.nAmount) || item.nAmount >= vecPrivateSendDenominations.back() * 10)
|
||||
nTotal += item.nAmount;
|
||||
}
|
||||
|
||||
@ -2231,7 +2231,7 @@ bool less_then_denom (const COutput& out1, const COutput& out2)
|
||||
|
||||
bool found1 = false;
|
||||
bool found2 = false;
|
||||
BOOST_FOREACH(CAmount d, darkSendDenominations) // loop through predefined denoms
|
||||
BOOST_FOREACH(CAmount d, vecPrivateSendDenominations) // loop through predefined denoms
|
||||
{
|
||||
if(pcoin1->vout[out1.i].nValue == d) found1 = true;
|
||||
if(pcoin2->vout[out2.i].nValue == d) found2 = true;
|
||||
@ -2392,7 +2392,7 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*
|
||||
//if we're doing only denominated, we need to round up to the nearest .1DRK
|
||||
if(coin_type == ONLY_DENOMINATED) {
|
||||
// Make outputs by looping through denominations, from large to small
|
||||
BOOST_FOREACH(CAmount v, darkSendDenominations)
|
||||
BOOST_FOREACH(CAmount v, vecPrivateSendDenominations)
|
||||
{
|
||||
BOOST_FOREACH(const COutput& out, vCoins)
|
||||
{
|
||||
@ -2638,7 +2638,7 @@ bool CWallet::SelectCoinsGrouppedByAddresses(std::vector<CompactTallyItem>& vecT
|
||||
if(fMasterNode && wtx.vout[i].nValue == 1000*COIN) continue;
|
||||
// ignore outputs that are 10 times smaller then the smallest denomination
|
||||
// otherwise they will just lead to higher fee / lower priority
|
||||
if(wtx.vout[i].nValue <= darkSendDenominations.back()/10) continue;
|
||||
if(wtx.vout[i].nValue <= vecPrivateSendDenominations.back()/10) continue;
|
||||
// ignore anonymized
|
||||
if(GetInputPrivateSendRounds(CTxIn(wtx.GetHash(), i)) >= nPrivateSendRounds) continue;
|
||||
}
|
||||
@ -3421,7 +3421,7 @@ string CWallet::PrepareDarksendDenominate(int minRounds, int maxRounds)
|
||||
if (IsLocked())
|
||||
return _("Error: Wallet locked, unable to create transaction!");
|
||||
|
||||
if(darkSendPool.GetState() != POOL_STATUS_ERROR && darkSendPool.GetState() != POOL_STATUS_SUCCESS)
|
||||
if(darkSendPool.GetState() != POOL_STATE_ERROR && darkSendPool.GetState() != POOL_STATE_SUCCESS)
|
||||
if(darkSendPool.GetEntriesCount() > 0)
|
||||
return _("Error: You already have pending entries in the PrivateSend pool");
|
||||
|
||||
@ -3438,7 +3438,7 @@ string CWallet::PrepareDarksendDenominate(int minRounds, int maxRounds)
|
||||
if minRounds >= 0 it means only denominated inputs are going in and coming out
|
||||
*/
|
||||
if(minRounds >= 0){
|
||||
if (!SelectCoinsByDenominations(darkSendPool.sessionDenom, 0.1*COIN, DARKSEND_POOL_MAX, vCoins, vCoins2, nValueIn, minRounds, maxRounds))
|
||||
if (!SelectCoinsByDenominations(darkSendPool.nSessionDenom, 0.1*COIN, DARKSEND_POOL_MAX, vCoins, vCoins2, nValueIn, minRounds, maxRounds))
|
||||
return _("Error: Can't select current denominated inputs");
|
||||
}
|
||||
|
||||
@ -3465,13 +3465,13 @@ string CWallet::PrepareDarksendDenominate(int minRounds, int maxRounds)
|
||||
int nStepsMax = 5 + GetRandInt(5);
|
||||
while(nStep < nStepsMax) {
|
||||
|
||||
BOOST_FOREACH(CAmount v, darkSendDenominations){
|
||||
BOOST_FOREACH(CAmount v, vecPrivateSendDenominations){
|
||||
// only use the ones that are approved
|
||||
bool fAccepted = false;
|
||||
if((darkSendPool.sessionDenom & (1 << 0)) && v == ((100*COIN) +100000)) {fAccepted = true;}
|
||||
else if((darkSendPool.sessionDenom & (1 << 1)) && v == ((10*COIN) +10000)) {fAccepted = true;}
|
||||
else if((darkSendPool.sessionDenom & (1 << 2)) && v == ((1*COIN) +1000)) {fAccepted = true;}
|
||||
else if((darkSendPool.sessionDenom & (1 << 3)) && v == ((.1*COIN) +100)) {fAccepted = true;}
|
||||
if((darkSendPool.nSessionDenom & (1 << 0)) && v == ((100*COIN) +100000)) {fAccepted = true;}
|
||||
else if((darkSendPool.nSessionDenom & (1 << 1)) && v == ((10*COIN) +10000)) {fAccepted = true;}
|
||||
else if((darkSendPool.nSessionDenom & (1 << 2)) && v == ((1*COIN) +1000)) {fAccepted = true;}
|
||||
else if((darkSendPool.nSessionDenom & (1 << 3)) && v == ((.1*COIN) +100)) {fAccepted = true;}
|
||||
if(!fAccepted) continue;
|
||||
|
||||
// try to add it
|
||||
@ -3522,7 +3522,7 @@ string CWallet::PrepareDarksendDenominate(int minRounds, int maxRounds)
|
||||
UnlockCoin(v.prevout);
|
||||
}
|
||||
|
||||
if(darkSendPool.GetDenominations(vOut) != darkSendPool.sessionDenom) {
|
||||
if(darkSendPool.GetDenominations(vOut) != darkSendPool.nSessionDenom) {
|
||||
// unlock used coins on failure
|
||||
LOCK(cs_wallet);
|
||||
BOOST_FOREACH(CTxIn v, vCoinsResult)
|
||||
@ -4261,7 +4261,7 @@ int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet, bool enableIX)
|
||||
}
|
||||
}
|
||||
|
||||
if(enableIX && nResult < 6 && IsLockedIXTransaction(GetHash()))
|
||||
if(enableIX && nResult < 6 && IsLockedInstandSendTransaction(GetHash()))
|
||||
return nInstantSendDepth + nResult;
|
||||
|
||||
return nResult;
|
||||
|
Loading…
Reference in New Issue
Block a user