Merge branch 'v0.12.0.x' of https://github.com/dashpay/dash into v0.12.0.x

This commit is contained in:
Evan Duffield 2015-07-14 07:55:07 -07:00
commit d228b4bf47
15 changed files with 383 additions and 360 deletions

View File

@ -17,63 +17,64 @@ void CActiveMasternode::ManageStatus()
if (fDebug) LogPrintf("CActiveMasternode::ManageStatus() - Begin\n");
//need correct adjusted time to send ping
bool fIsInitialDownload = IsInitialBlockDownload();
if(fIsInitialDownload) {
//need correct blocks to send ping
if(IsInitialBlockDownload()) {
status = MASTERNODE_SYNC_IN_PROCESS;
LogPrintf("CActiveMasternode::ManageStatus() - Sync in progress. Must wait until sync is complete to start Masternode.\n");
return;
}
if(status == MASTERNODE_INPUT_TOO_NEW || status == MASTERNODE_NOT_CAPABLE || status == MASTERNODE_SYNC_IN_PROCESS){
status = MASTERNODE_NOT_PROCESSED;
if(status == MASTERNODE_INITIAL || status == MASTERNODE_SYNC_IN_PROCESS) {
CMasternode *pmn;
pmn = mnodeman.Find(pubKeyMasternode);
if(pmn != NULL) {
pmn->Check();
if(pmn->IsEnabled()) EnableHotColdMasterNode(pmn->vin, pmn->addr);
}
}
if(status == MASTERNODE_NOT_PROCESSED) {
if(status != MASTERNODE_STARTED) {
// Set defaults
status = MASTERNODE_NOT_CAPABLE;
notCapableReason = "";
if(strMasterNodeAddr.empty()) {
if(!GetLocal(service)) {
notCapableReason = "Can't detect external address. Please use the Masternodeaddr configuration option.";
status = MASTERNODE_NOT_CAPABLE;
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason.c_str());
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
return;
}
} else {
service = CService(strMasterNodeAddr);
}
LogPrintf("CActiveMasternode::ManageStatus() - Checking inbound connection to '%s'\n", service.ToString().c_str());
LogPrintf("CActiveMasternode::ManageStatus() - Checking inbound connection to '%s'\n", service.ToString());
if(Params().NetworkID() == CBaseChainParams::MAIN) {
if(service.GetPort() != 9999) {
notCapableReason = "Invalid port: " + boost::lexical_cast<string>(service.GetPort()) + " - only 9999 is supported on mainnet.";
status = MASTERNODE_NOT_CAPABLE;
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason.c_str());
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
return;
}
} else if(service.GetPort() == 9999) {
notCapableReason = "Invalid port: " + boost::lexical_cast<string>(service.GetPort()) + " - 9999 is only supported on mainnet.";
status = MASTERNODE_NOT_CAPABLE;
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason.c_str());
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
return;
}
if(!ConnectNode((CAddress)service, service.ToString().c_str())){
notCapableReason = "Could not connect to " + service.ToString();
status = MASTERNODE_NOT_CAPABLE;
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason.c_str());
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
return;
}
if(pwalletMain->IsLocked()){
notCapableReason = "Wallet is locked.";
status = MASTERNODE_NOT_CAPABLE;
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason.c_str());
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
return;
}
// Set defaults
status = MASTERNODE_NOT_CAPABLE;
notCapableReason = "Unknown. Check debug.log for more information.";
// Choose coins to use
CPubKey pubKeyCollateralAddress;
@ -84,16 +85,11 @@ void CActiveMasternode::ManageStatus()
if(GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS){
notCapableReason = "Input must have least " + boost::lexical_cast<string>(MASTERNODE_MIN_CONFIRMATIONS) +
" confirmations - " + boost::lexical_cast<string>(GetInputAge(vin)) + " confirmations";
LogPrintf("CActiveMasternode::ManageStatus() - %s\n", notCapableReason.c_str());
LogPrintf("CActiveMasternode::ManageStatus() - %s\n", notCapableReason);
status = MASTERNODE_INPUT_TOO_NEW;
return;
}
LogPrintf("CActiveMasternode::ManageStatus() - Is capable master node!\n");
status = MASTERNODE_IS_CAPABLE;
notCapableReason = "";
pwalletMain->LockCoin(vin.prevout);
// send to all nodes
@ -102,31 +98,48 @@ void CActiveMasternode::ManageStatus()
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
{
LogPrintf("Register::ManageStatus() - Error upon calling SetKey: %s\n", errorMessage.c_str());
notCapableReason = "Error upon calling SetKey: " + errorMessage;
LogPrintf("Register::ManageStatus() - %s\n", notCapableReason);
return;
}
if(!Register(vin, service, keyCollateralAddress, pubKeyCollateralAddress, keyMasternode, pubKeyMasternode, errorMessage)) {
LogPrintf("CActiveMasternode::ManageStatus() - Error on Register: %s\n", errorMessage.c_str());
notCapableReason = "Error on Register: " + errorMessage;
LogPrintf("Register::ManageStatus() - %s\n", notCapableReason);
return;
}
LogPrintf("CActiveMasternode::ManageStatus() - Is capable master node!\n");
status = MASTERNODE_STARTED;
return;
} else {
notCapableReason = "Could not find suitable coins!";
LogPrintf("CActiveMasternode::ManageStatus() - %s\n", notCapableReason.c_str());
LogPrintf("CActiveMasternode::ManageStatus() - %s\n", notCapableReason);
return;
}
}
//send to all peers
if(!Mnping(errorMessage)) {
LogPrintf("CActiveMasternode::ManageStatus() - Error on Ping: %s\n", errorMessage.c_str());
if(!SendMasternodePing(errorMessage)) {
LogPrintf("CActiveMasternode::ManageStatus() - Error on Ping: %s\n", errorMessage);
}
}
bool CActiveMasternode::Mnping(std::string& errorMessage) {
if(status != MASTERNODE_IS_CAPABLE && status != MASTERNODE_REMOTELY_ENABLED) {
std::string CActiveMasternode::GetStatus() {
switch (status) {
case MASTERNODE_INITIAL: return "node just started, not yet activated";
case MASTERNODE_SYNC_IN_PROCESS: return "sync in process. Must wait until client is synced to start";
case MASTERNODE_INPUT_TOO_NEW: return "masternode input must have at least 15 confirmations";
case MASTERNODE_NOT_CAPABLE: return "not capable masternode: " + notCapableReason;
case MASTERNODE_STARTED: return "masternode successfully started";
default: return "unknown";
}
}
bool CActiveMasternode::SendMasternodePing(std::string& errorMessage) {
if(status != MASTERNODE_STARTED) {
errorMessage = "Masternode is not in a running status";
LogPrintf("CActiveMasternode::Mnping() - Error: %s\n", errorMessage.c_str());
return false;
}
@ -135,43 +148,42 @@ bool CActiveMasternode::Mnping(std::string& errorMessage) {
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
{
LogPrintf("CActiveMasternode::Mnping() - Error upon calling SetKey: %s\n", errorMessage.c_str());
errorMessage = strprintf("Error upon calling SetKey: %s\n", errorMessage);
return false;
}
return Mnping(vin, service, keyMasternode, pubKeyMasternode, errorMessage);
}
bool CActiveMasternode::Mnping(CTxIn vin, CService service, CKey keyMasternode, CPubKey pubKeyMasternode, std::string &retErrorMessage) {
//send to all peers
LogPrintf("CActiveMasternode::Mnping() - RelayMasternodeEntryPing vin = %s\n", vin.ToString().c_str());
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";
return false;
}
// Update Last Seen timestamp in Masternode list
// Update lastPing for our masternode in Masternode list
CMasternode* pmn = mnodeman.Find(vin);
if(pmn != NULL)
{
pmn->UpdateLastSeen();
if(pmn->IsPingedWithin(MASTERNODE_PING_SECONDS, mnp.sigTime)){
errorMessage = "Too early to send Masternode Ping";
return false;
}
pmn->lastPing = mnp;
mapSeenMasternodePing[mnp.GetHash()] = mnp;
mnp.Relay();
return true;
}
else
{
// Seems like we are trying to send a ping while the Masternode is not registered in the network
retErrorMessage = "Darksend Masternode List doesn't include our Masternode, shutting down Masternode pinging service! " + vin.ToString();
LogPrintf("CActiveMasternode::Mnping() - Error: %s\n", retErrorMessage.c_str());
errorMessage = "Darksend Masternode List doesn't include our Masternode, shutting down Masternode pinging service! " + vin.ToString();
status = MASTERNODE_NOT_CAPABLE;
notCapableReason = retErrorMessage;
notCapableReason = errorMessage;
return false;
}
mapSeenMasternodePing[mnp.GetHash()] = mnp;
mnp.Relay();
return true;
}
bool CActiveMasternode::Register(std::string strService, std::string strKeyMasternode, std::string txHash, std::string strOutputIndex, std::string& errorMessage) {
@ -183,13 +195,13 @@ bool CActiveMasternode::Register(std::string strService, std::string strKeyMaste
if(!darkSendSigner.SetKey(strKeyMasternode, errorMessage, keyMasternode, pubKeyMasternode))
{
LogPrintf("CActiveMasternode::Register() - Error upon calling SetKey: %s\n", errorMessage.c_str());
LogPrintf("CActiveMasternode::Register() - Error upon calling SetKey: %s\n", errorMessage);
return false;
}
if(!GetMasterNodeVin(vin, pubKeyCollateralAddress, keyCollateralAddress, txHash, strOutputIndex)) {
errorMessage = "could not allocate vin";
LogPrintf("CActiveMasternode::Register() - Error: %s\n", errorMessage.c_str());
LogPrintf("CActiveMasternode::Register() - Error: %s\n", errorMessage);
return false;
}
@ -197,32 +209,35 @@ bool CActiveMasternode::Register(std::string strService, std::string strKeyMaste
}
bool CActiveMasternode::Register(CTxIn vin, CService service, CKey keyCollateralAddress, CPubKey pubKeyCollateralAddress, CKey keyMasternode, CPubKey pubKeyMasternode, std::string &retErrorMessage) {
CMasternodeBroadcast mnb;
CMasternodePing mnp(vin);
if(!mnp.Sign(keyMasternode, pubKeyMasternode)){
LogPrintf("CActiveMasternode::Register() - Failed to sign ping, vin: %s\n", vin.ToString());
return false;
}
mapSeenMasternodePing[mnp.GetHash()] = mnp;
LogPrintf("CActiveMasternode::Register() - Adding to Masternode list service: %s - vin: %s\n", service.ToString(), vin.ToString());
mnb = CMasternodeBroadcast(service, vin, pubKeyCollateralAddress, pubKeyMasternode, PROTOCOL_VERSION);
mnb.lastPing = mnp;
if(!mnb.Sign(keyCollateralAddress)){
LogPrintf("CActiveMasternode::Register() - Failed to sign broadcast, vin: %s\n", vin.ToString());
return false;
}
mapSeenMasternodeBroadcast[mnb.GetHash()] = mnb;
CMasternode* pmn = mnodeman.Find(vin);
if(pmn == NULL)
{
LogPrintf("CActiveMasternode::Register() - Adding to Masternode list service: %s - vin: %s\n", service.ToString().c_str(), vin.ToString().c_str());
CMasternodeBroadcast mnb(service, vin, pubKeyCollateralAddress, pubKeyMasternode, PROTOCOL_VERSION);
if(!mnb.Sign(keyCollateralAddress)){
//send to all peers
LogPrintf("CActiveMasternode::Register() - Failed to sign %s\n", vin.ToString().c_str());
return false;
}
CMasternode mn(mnb);
mn.UpdateLastSeen();
mnodeman.Add(mn);
} else {
pmn->UpdateFromNewBroadcast(mnb);
}
if(pmn == NULL) pmn = mnodeman.Find(vin);
if(pmn != NULL)
{
CMasternodeBroadcast mnb(*pmn);
mapSeenMasternodeBroadcast[mnb.GetHash()] = mnb;
//send to all peers
LogPrintf("CActiveMasternode::Register() - RelayElectionEntry vin = %s\n", vin.ToString().c_str());
mnb.Relay(false);
}
//send to all peers
LogPrintf("CActiveMasternode::Register() - RelayElectionEntry vin = %s\n", vin.ToString());
mnb.Relay();
return true;
}
@ -232,8 +247,6 @@ bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secr
}
bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey, std::string strTxHash, std::string strOutputIndex) {
CScript pubScript;
// Find possible candidates
vector<COutput> possibleCoins = SelectCoinsMasternode();
COutput *selectedOutput;
@ -340,7 +353,7 @@ bool CActiveMasternode::EnableHotColdMasterNode(CTxIn& newVin, CService& newServ
{
if(!fMasterNode) return false;
status = MASTERNODE_REMOTELY_ENABLED;
status = MASTERNODE_STARTED;
//The values below are needed for signing mnping messages going forward
this->vin = newVin;

View File

@ -16,6 +16,20 @@
// Responsible for activating the Masternode and pinging the network
class CActiveMasternode
{
private:
// critical section to protect the inner data structures
mutable CCriticalSection cs;
/// Ping Masternode
bool SendMasternodePing(std::string& errorMessage);
/// Register any Masternode
bool Register(CTxIn vin, CService service, CKey key, CPubKey pubKey, CKey keyMasternode, CPubKey pubKeyMasternode, std::string &retErrorMessage);
/// Get 1000DRK input that can be used for the Masternode
bool GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey, std::string strTxHash, std::string strOutputIndex);
bool GetVinFromOutput(COutput out, CTxIn& vin, CPubKey& pubkey, CKey& secretKey);
public:
// Initialized by init.cpp
// Keys for the main Masternode
@ -30,29 +44,21 @@ public:
CActiveMasternode()
{
status = MASTERNODE_NOT_PROCESSED;
status = MASTERNODE_INITIAL;
}
/// Manage status of main Masternode
void ManageStatus();
/// Ping for main Masternode
bool Mnping(std::string& errorMessage);
/// Ping for any Masternode
bool Mnping(CTxIn vin, CService service, CKey key, CPubKey pubKey, std::string &retErrorMessage);
std::string GetStatus();
/// Register remote Masternode
bool Register(std::string strService, std::string strKey, std::string txHash, std::string strOutputIndex, std::string& errorMessage);
/// Register any Masternode
bool Register(CTxIn vin, CService service, CKey key, CPubKey pubKey, CKey keyMasternode, CPubKey pubKeyMasternode, std::string &retErrorMessage);
/// Get 1000DRK input that can be used for the Masternode
bool GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey);
bool GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey, std::string strTxHash, std::string strOutputIndex);
vector<COutput> SelectCoinsMasternode();
bool GetVinFromOutput(COutput out, CTxIn& vin, CPubKey& pubkey, CKey& secretKey);
/// Enable hot wallet mode (run a Masternode with no funds)
/// Enable cold wallet mode (run a Masternode with no funds)
bool EnableHotColdMasterNode(CTxIn& vin, CService& addr);
};

View File

@ -22,8 +22,6 @@
using namespace std;
using namespace boost;
CCriticalSection cs_darksend;
// The main object for accessing Darksend
CDarksendPool darkSendPool;
// A helper object for signing messages from Masternodes
@ -2335,27 +2333,6 @@ void ThreadCheckDarkSendPool()
MilliSleep(1000);
//LogPrintf("ThreadCheckDarkSendPool::check timeout\n");
darkSendPool.CheckTimeout();
darkSendPool.CheckForCompleteQueue();
if(c % 60 == 0)
{
LOCK(cs_main);
/*
cs_main is required for doing CMasternode.Check because something
is modifying the coins view without a mempool lock. It causes
segfaults from this code without the cs_main lock.
*/
mnodeman.CheckAndRemove();
mnodeman.ProcessMasternodeConnections();
masternodePayments.CleanPaymentList();
CleanTransactionLocksList();
}
if(c % MASTERNODE_PING_SECONDS == 0) activeMasternode.ManageStatus();
if(c % MASTERNODES_DUMP_SECONDS == 0) DumpMasternodes();
//try to sync the Masternode list and payment list every 5 seconds from at least 3 nodes
if(c % 5 == 0 && RequestedMasternodeAssets <= 5){
bool fIsInitialDownload = IsInitialBlockDownload();
@ -2403,8 +2380,10 @@ void ThreadCheckDarkSendPool()
}
}
}
} else if(c % 60 == 0 && RequestedMasternodeAssets == 3){
RequestedMasternodeAssets = MASTERNODE_LIST_SYNCED; //done syncing
} else if((c % 60 == 0 && RequestedMasternodeAssets >= 5 && RequestedMasternodeAssets < MASTERNODE_LIST_SYNCED) || //done syncing
(c % (5 * 60) == 0 && RequestedMasternodeAssets < 5)) { //couldn't find 5 peers in 5 minutes
RequestedMasternodeAssets = MASTERNODE_LIST_SYNCED;
c = 1; // reset counter
}
if(c % 60 == 0){
@ -2417,8 +2396,37 @@ void ThreadCheckDarkSendPool()
}
}
if(darkSendPool.GetState() == POOL_STATUS_IDLE && c % 6 == 0){
darkSendPool.DoAutomaticDenominating();
if(RequestedMasternodeAssets == MASTERNODE_LIST_SYNCED) {
if(c % MASTERNODE_PING_SECONDS == 1) activeMasternode.ManageStatus(); // activate right after sync
if(c % 60 == 0)
{
LOCK(cs_main);
/*
cs_main is required for doing CMasternode.Check because something
is modifying the coins view without a mempool lock. It causes
segfaults from this code without the cs_main lock.
*/
mnodeman.CheckAndRemove();
mnodeman.ProcessMasternodeConnections();
masternodePayments.CleanPaymentList();
CleanTransactionLocksList();
}
if(c % 60 == 0){
//if we've used 1/5 of the Masternode list, then clear the list.
if((int)vecMasternodesUsed.size() > (int)mnodeman.size() / 5)
vecMasternodesUsed.clear();
}
if(c % MASTERNODES_DUMP_SECONDS == 0) DumpMasternodes();
darkSendPool.CheckTimeout();
darkSendPool.CheckForCompleteQueue();
if(darkSendPool.GetState() == POOL_STATUS_IDLE && c % 6 == 0){
darkSendPool.DoAutomaticDenominating();
}
}
}
}

View File

@ -267,6 +267,9 @@ public:
*/
class CDarksendPool
{
private:
mutable CCriticalSection cs_darksend;
public:
enum messages {
ERR_ALREADY_HAVE,

View File

@ -1490,7 +1490,6 @@ bool AppInit2(boost::thread_group& threadGroup)
return InitError(_("You must specify a masternodeprivkey in the configuration. Please see documentation for help."));
}
if(Params().NetworkID() != CBaseChainParams::REGTEST) activeMasternode.ManageStatus();
}
if(GetBoolArg("-mnconflock", true)) {

View File

@ -27,7 +27,7 @@ class CConsensusVote;
class CTransaction;
class CTransactionLock;
static const int MIN_INSTANTX_PROTO_VERSION = 70089;
static const int MIN_INSTANTX_PROTO_VERSION = 70090;
extern map<uint256, CTransaction> mapTxLockReq;
extern map<uint256, CTransaction> mapTxLockReqRejected;

View File

@ -4180,11 +4180,9 @@ void static ProcessGetData(CNode* pfrom)
if (!pushed && inv.type == MSG_MASTERNODE_ANNOUNCE) {
if(mapSeenMasternodeBroadcast.count(inv.hash)){
bool fRequested = false; // Requested full masternode list
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << mapSeenMasternodeBroadcast[inv.hash];
ss << fRequested;
pfrom->PushMessage("mnb", ss);
pushed = true;
}
@ -4192,11 +4190,9 @@ void static ProcessGetData(CNode* pfrom)
if (!pushed && inv.type == MSG_MASTERNODE_PING) {
if(mapSeenMasternodePing.count(inv.hash)){
bool fRequested = false; // Requested full masternode list
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << mapSeenMasternodePing[inv.hash];
ss << fRequested;
pfrom->PushMessage("mnp", ss);
pushed = true;
}

View File

@ -40,8 +40,8 @@ bool IsBudgetCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, s
CTransaction txCollateral;
uint256 nBlockHash;
if(!GetTransaction(nTxCollateralHash, txCollateral, nBlockHash, true)){
strError = "Can't find collateral tx %s\n", txCollateral.ToString().c_str();
LogPrintf ("CBudgetProposalBroadcast::FeeTXValid - Can't find collateral tx %s\n", txCollateral.ToString().c_str());
strError = strprintf("Can't find collateral tx %s", txCollateral.ToString());
LogPrintf ("CBudgetProposalBroadcast::IsBudgetCollateralValid - %s\n", strError);
return false;
}
@ -54,16 +54,16 @@ bool IsBudgetCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, s
bool foundOpReturn = false;
BOOST_FOREACH(const CTxOut o, txCollateral.vout){
if(!o.scriptPubKey.IsNormalPaymentScript() && !o.scriptPubKey.IsUnspendable()){
strError = "Invalid Script";
LogPrintf ("CBudgetProposalBroadcast::FeeTXValid - Invalid Script %s\n", txCollateral.ToString());
strError = strprintf("Invalid Script %s", txCollateral.ToString());
LogPrintf ("CBudgetProposalBroadcast::IsBudgetCollateralValid - %s\n", strError);
return false;
}
if(o.scriptPubKey == findScript && o.nValue >= BUDGET_FEE_TX) foundOpReturn = true;
}
if(!foundOpReturn){
strError = "Couldn't find opReturn";
LogPrintf ("CBudgetProposalBroadcast::IsBudgetCollateralValid - Couldn't find opReturn %s\n", txCollateral.ToString());
strError = strprintf("Couldn't find opReturn %s", txCollateral.ToString());
LogPrintf ("CBudgetProposalBroadcast::IsBudgetCollateralValid - %s\n", strError);
return false;
}
@ -79,8 +79,8 @@ bool IsBudgetCollateralValid(uint256 nTxCollateralHash, uint256 nExpectedHash, s
}
if(conf < BUDGET_FEE_CONFIRMATIONS){
strError = "Collateral requires at least 6 confirmations - " + boost::lexical_cast<std::string>(conf) + " confirmations ";
LogPrintf ("CBudgetProposalBroadcast::IsBudgetCollateralValid - Collateral requires at least 6 confirmations - %s - %d confirmations\n", txCollateral.GetHash().ToString(), conf);
strError = strprintf("Collateral requires at least %d confirmations - %d confirmations", BUDGET_FEE_CONFIRMATIONS, conf);
LogPrintf ("CBudgetProposalBroadcast::IsBudgetCollateralValid - %s - %d confirmations\n", strError, conf);
return false;
}

View File

@ -73,8 +73,7 @@ CMasternode::CMasternode()
sig = std::vector<unsigned char>();
activeState = MASTERNODE_ENABLED;
sigTime = GetAdjustedTime();
lastMnping = 0;
lastTimeSeen = 0;
lastPing = CMasternodePing();
cacheInputAge = 0;
cacheInputAgeBlock = 0;
unitTest = false;
@ -96,8 +95,7 @@ CMasternode::CMasternode(const CMasternode& other)
sig = other.sig;
activeState = other.activeState;
sigTime = other.sigTime;
lastMnping = other.lastMnping;
lastTimeSeen = other.lastTimeSeen;
lastPing = other.lastPing;
cacheInputAge = other.cacheInputAge;
cacheInputAgeBlock = other.cacheInputAgeBlock;
unitTest = other.unitTest;
@ -109,29 +107,6 @@ CMasternode::CMasternode(const CMasternode& other)
nVotedTimes = other.nVotedTimes;
}
CMasternode::CMasternode(CService newAddr, CTxIn newVin, CPubKey newPubkey, std::vector<unsigned char> newSig, int64_t newSigTime, CPubKey newPubkey2, int protocolVersionIn)
{
LOCK(cs);
vin = newVin;
addr = newAddr;
pubkey = newPubkey;
pubkey2 = newPubkey2;
sig = newSig;
activeState = MASTERNODE_ENABLED;
sigTime = newSigTime;
lastMnping = 0;
lastTimeSeen = 0;
cacheInputAge = 0;
cacheInputAgeBlock = 0;
unitTest = false;
allowFreeTx = true;
protocolVersion = protocolVersionIn;
nLastDsq = 0;
nScanningErrorCount = 0;
nLastScanningErrorBlockHeight = 0;
nVotedTimes = 0;
}
CMasternode::CMasternode(const CMasternodeBroadcast& mnb)
{
LOCK(cs);
@ -142,8 +117,7 @@ CMasternode::CMasternode(const CMasternodeBroadcast& mnb)
sig = mnb.sig;
activeState = MASTERNODE_ENABLED;
sigTime = mnb.sigTime;
lastMnping = 0;
lastTimeSeen = 0;
lastPing = mnb.lastPing;
cacheInputAge = 0;
cacheInputAgeBlock = 0;
unitTest = false;
@ -165,6 +139,11 @@ void CMasternode::UpdateFromNewBroadcast(CMasternodeBroadcast& mnb)
sig = mnb.sig;
protocolVersion = mnb.protocolVersion;
addr = mnb.addr;
int nDoS = 0;
if(mnb.lastPing == CMasternodePing() || (mnb.lastPing != CMasternodePing() && mnb.lastPing.CheckAndUpdate(nDoS))) {
lastPing = mnb.lastPing;
mapSeenMasternodePing[lastPing.GetHash()] = lastPing;
}
}
//
@ -201,12 +180,12 @@ void CMasternode::Check()
if(activeState == MASTERNODE_VIN_SPENT) return;
if(!UpdatedWithin(MASTERNODE_REMOVAL_SECONDS)){
if(!IsPingedWithin(MASTERNODE_REMOVAL_SECONDS)){
activeState = MASTERNODE_REMOVE;
return;
}
if(!UpdatedWithin(MASTERNODE_EXPIRATION_SECONDS)){
if(!IsPingedWithin(MASTERNODE_EXPIRATION_SECONDS)){
activeState = MASTERNODE_EXPIRED;
return;
}
@ -260,8 +239,7 @@ CMasternodeBroadcast::CMasternodeBroadcast()
sig = std::vector<unsigned char>();
activeState = MASTERNODE_ENABLED;
sigTime = GetAdjustedTime();
lastMnping = 0;
lastTimeSeen = 0;
lastPing = CMasternodePing();
cacheInputAge = 0;
cacheInputAgeBlock = 0;
unitTest = false;
@ -280,8 +258,7 @@ CMasternodeBroadcast::CMasternodeBroadcast(CService newAddr, CTxIn newVin, CPubK
sig = std::vector<unsigned char>();
activeState = MASTERNODE_ENABLED;
sigTime = GetAdjustedTime();
lastMnping = 0;
lastTimeSeen = 0;
lastPing = CMasternodePing();
cacheInputAge = 0;
cacheInputAgeBlock = 0;
unitTest = false;
@ -292,32 +269,32 @@ CMasternodeBroadcast::CMasternodeBroadcast(CService newAddr, CTxIn newVin, CPubK
nLastScanningErrorBlockHeight = 0;
}
CMasternodeBroadcast::CMasternodeBroadcast(const CMasternode& other)
CMasternodeBroadcast::CMasternodeBroadcast(const CMasternode& mn)
{
vin = other.vin;
addr = other.addr;
pubkey = other.pubkey;
pubkey2 = other.pubkey2;
sig = other.sig;
activeState = other.activeState;
sigTime = other.sigTime;
lastMnping = other.lastMnping;
lastTimeSeen = other.lastTimeSeen;
cacheInputAge = other.cacheInputAge;
cacheInputAgeBlock = other.cacheInputAgeBlock;
unitTest = other.unitTest;
allowFreeTx = other.allowFreeTx;
protocolVersion = other.protocolVersion;
nLastDsq = other.nLastDsq;
nScanningErrorCount = other.nScanningErrorCount;
nLastScanningErrorBlockHeight = other.nLastScanningErrorBlockHeight;
vin = mn.vin;
addr = mn.addr;
pubkey = mn.pubkey;
pubkey2 = mn.pubkey2;
sig = mn.sig;
activeState = mn.activeState;
sigTime = mn.sigTime;
lastPing = mn.lastPing;
cacheInputAge = mn.cacheInputAge;
cacheInputAgeBlock = mn.cacheInputAgeBlock;
unitTest = mn.unitTest;
allowFreeTx = mn.allowFreeTx;
protocolVersion = mn.protocolVersion;
nLastDsq = mn.nLastDsq;
nScanningErrorCount = mn.nScanningErrorCount;
nLastScanningErrorBlockHeight = mn.nLastScanningErrorBlockHeight;
}
bool CMasternodeBroadcast::CheckAndUpdate(int& nDos, bool fRequested)
bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
{
// make sure signature isn't in the future (past is OK)
if (sigTime > GetAdjustedTime() + 60 * 60) {
LogPrintf("mnb - Signature rejected, too far into the future %s\n", vin.ToString().c_str());
LogPrintf("mnb - Signature rejected, too far into the future %s\n", vin.ToString());
nDos = 1;
return false;
}
@ -367,35 +344,39 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos, bool fRequested)
//search existing Masternode list, this is where we update existing Masternodes with new mnb broadcasts
CMasternode* pmn = mnodeman.Find(vin);
// if we are masternode but with undefined vin and this mnb is ours (matches our Masternode privkey) then just skip this part
if(pmn != NULL && !(fMasterNode && activeMasternode.vin == CTxIn() && pubkey2 == activeMasternode.pubKeyMasternode))
{
// if Requested, we don't want to update this info
if(fRequested) { Relay(false); return true;}
// no such masternode or it's not enabled already, nothing to update
if(pmn == NULL || (pmn != NULL && !pmn->IsEnabled())) return true;
// mn.pubkey = pubkey, IsVinAssociatedWithPubkey is validated once below,
// after that they just need to match
if(pmn->pubkey == pubkey && !pmn->UpdatedWithin(MASTERNODE_MIN_MNB_SECONDS)){
pmn->UpdateLastSeen();
if(pmn->sigTime < sigTime){ //take the newest entry
LogPrintf("mnb - Got updated entry for %s\n", addr.ToString().c_str());
pmn->UpdateFromNewBroadcast((*this));
pmn->Check();
if(pmn->IsEnabled()) {
Relay(fRequested);
}
}
}
// mn.pubkey = pubkey, IsVinAssociatedWithPubkey is validated once below,
// after that they just need to match
if(pmn->pubkey == pubkey && !pmn->IsBroadcastedWithin(MASTERNODE_MIN_MNB_SECONDS)) {
//take the newest entry
LogPrintf("mnb - Got updated entry for %s\n", addr.ToString().c_str());
pmn->UpdateFromNewBroadcast((*this));
pmn->Check();
if(pmn->IsEnabled()) Relay();
}
return true;
}
bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS, bool fRequested)
bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS)
{
// we are a masternode with the same vin (i.e. already activated) and this mnb is ours (matches our Masternode privkey)
// so nothing to do here for us
if(fMasterNode && vin.prevout == activeMasternode.vin.prevout && pubkey2 == activeMasternode.pubKeyMasternode)
return true;
// search existing Masternode list
CMasternode* pmn = mnodeman.Find(vin);
if(pmn != NULL) {
// nothing to do here if we already know about this masternode and it's enabled
if(pmn->IsEnabled()) return true;
// if it's not enabled, remove old MN first and continue
else mnodeman.Remove(pmn->vin);
}
CValidationState state;
CMutableTransaction tx = CMutableTransaction();
CTxOut vout = CTxOut(999.99*COIN, darkSendPool.collateralPubKey);
@ -427,9 +408,8 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS, bool fRequested)
}
}
// add our Masternode
CMasternode mn((*this));
mn.UpdateLastSeen(lastTimeSeen);
LogPrintf("mnb - Got NEW Masternode entry %s %s\n", addr.ToString(), vin.ToString());
CMasternode mn(*this);
mnodeman.Add(mn);
// if it matches our Masternode privkey, then we've been remotely activated
@ -440,7 +420,7 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS, bool fRequested)
bool isLocal = addr.IsRFC1918() || addr.IsLocal();
if(Params().NetworkID() == CBaseChainParams::REGTEST) isLocal = false;
if(!fRequested && !isLocal) Relay(fRequested);
if(!isLocal) Relay();
return true;
} else {
@ -451,7 +431,7 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS, bool fRequested)
return false;
}
void CMasternodeBroadcast::Relay(bool fRequested)
void CMasternodeBroadcast::Relay()
{
CInv inv(MSG_MASTERNODE_ANNOUNCE, GetHash());
RelayInv(inv);
@ -484,13 +464,17 @@ bool CMasternodeBroadcast::Sign(CKey& keyCollateralAddress)
CMasternodePing::CMasternodePing()
{
vin = CTxIn();
blockHash = chainActive[chainActive.Height() - 12]->GetBlockHash();
blockHash = uint256(0);
sigTime = 0;
vchSig = std::vector<unsigned char>();
}
CMasternodePing::CMasternodePing(CTxIn& newVin)
{
vin = newVin;
blockHash = chainActive[chainActive.Height() - 12]->GetBlockHash();
sigTime = GetAdjustedTime();
vchSig = std::vector<unsigned char>();
}
@ -518,62 +502,70 @@ bool CMasternodePing::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
bool CMasternodePing::CheckAndUpdate(int& nDos)
{
if (sigTime > GetAdjustedTime() + 60 * 60) {
LogPrintf("mnping - Signature rejected, too far into the future %s\n", vin.ToString().c_str());
LogPrintf("CMasternodePing::CheckAndUpdate - Signature rejected, too far into the future %s\n", vin.ToString().c_str());
nDos = 1;
return false;
}
if (sigTime <= GetAdjustedTime() - 60 * 60) {
LogPrintf("mnping - Signature rejected, too far into the past %s - %d %d \n", vin.ToString().c_str(), sigTime, GetAdjustedTime());
LogPrintf("CMasternodePing::CheckAndUpdate - Signature rejected, too far into the past %s - %d %d \n", vin.ToString().c_str(), sigTime, GetAdjustedTime());
nDos = 1;
return false;
}
// see if we have this Masternode
CMasternode* pmn = mnodeman.Find(vin);
if(pmn != NULL && pmn->protocolVersion >= nMasternodeMinProtocol)
if(pmn != NULL && pmn->IsEnabled() && pmn->protocolVersion >= nMasternodeMinProtocol)
{
// LogPrintf("mnping - Found corresponding mn for vin: %s\n", vin.ToString().c_str());
// take this only if it's newer and last ping was more then MASTERNODE_MIN_MNP_SECONDS ago
if(sigTime - pmn->lastMnping > MASTERNODE_MIN_MNP_SECONDS-60)
// update only if there is no known ping for this masternode or
// last ping was more then MASTERNODE_MIN_MNP_SECONDS-60 ago comparing to this one
if(!pmn->IsPingedWithin(MASTERNODE_MIN_MNP_SECONDS - 60, sigTime))
{
std::string strMessage = vin.ToString() + blockHash.ToString() + boost::lexical_cast<std::string>(sigTime);
std::string errorMessage = "";
if(!darkSendSigner.VerifyMessage(pmn->pubkey2, vchSig, strMessage, errorMessage))
{
LogPrintf("mnping - Got bad Masternode address signature %s\n", vin.ToString());
LogPrintf("CMasternodePing::CheckAndUpdate - Got bad Masternode address signature %s\n", vin.ToString());
nDos = 33;
return false;
}
pmn->lastMnping = sigTime;
BlockMap::iterator mi = mapBlockIndex.find(blockHash);
if (mi != mapBlockIndex.end() && (*mi).second)
{
if((*mi).second->nHeight < chainActive.Height() - 24)
{
LogPrintf("mnping - Masternode %s block hash %s is too old\n", vin.ToString(), blockHash.ToString());
LogPrintf("CMasternodePing::CheckAndUpdate - Masternode %s block hash %s is too old\n", vin.ToString(), blockHash.ToString());
// Do nothing here (no Masternode update, no mnping relay)
// Let this node to be visible but fail to accept mnping
return false;
}
} else {
if (fDebug) LogPrintf("mnping - Masternode %s block hash %s is unknown\n", vin.ToString(), blockHash.ToString());
if (fDebug) LogPrintf("CMasternodePing::CheckAndUpdate - Masternode %s block hash %s is unknown\n", vin.ToString(), blockHash.ToString());
// maybe we stuck so we shouldn't ban this node, just fail to accept it
// TODO: or should we also request this block?
return false;
}
pmn->UpdateLastSeen();
pmn->lastPing = *this;
pmn->Check();
if(!pmn->IsEnabled()) return false;
if(fDebug) LogPrintf("CMasternodePing::CheckAndUpdate - Masternode ping accepted, vin: %s\n", vin.ToString());
Relay();
return true;
}
if(fDebug) LogPrintf("CMasternodePing::CheckAndUpdate - Masternode ping arrived too early, vin: %s\n", vin.ToString());
nDos = 1;
return false;
}
if(fDebug) LogPrintf("CMasternodePing::CheckAndUpdate - Couldn't find compatible Masternode entry, vin: %s\n", vin.ToString());
return false;
}

View File

@ -13,15 +13,11 @@
#include "main.h"
#include "timedata.h"
#define MASTERNODE_NOT_PROCESSED 0 // initial state
#define MASTERNODE_IS_CAPABLE 1
#define MASTERNODE_NOT_CAPABLE 2
#define MASTERNODE_STOPPED 3
#define MASTERNODE_INPUT_TOO_NEW 4
#define MASTERNODE_PORT_NOT_OPEN 6
#define MASTERNODE_PORT_OPEN 7
#define MASTERNODE_SYNC_IN_PROCESS 8
#define MASTERNODE_REMOTELY_ENABLED 9
#define MASTERNODE_INITIAL 0 // initial state
#define MASTERNODE_SYNC_IN_PROCESS 1
#define MASTERNODE_INPUT_TOO_NEW 2
#define MASTERNODE_NOT_CAPABLE 3
#define MASTERNODE_STARTED 4
#define MASTERNODE_MIN_CONFIRMATIONS 15
#define MASTERNODE_MIN_MNP_SECONDS (30*60)
@ -39,6 +35,75 @@ extern map<int64_t, uint256> mapCacheBlockHashes;
bool GetBlockHash(uint256& hash, int nBlockHeight);
//
// The Masternode Ping Class : Contains a different serialize method for sending pings from masternodes throughout the network
//
class CMasternodePing
{
public:
CTxIn vin;
uint256 blockHash;
int64_t sigTime; //mnb message times
std::vector<unsigned char> vchSig;
//removed stop
CMasternodePing();
CMasternodePing(CTxIn& newVin);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(vin);
READWRITE(blockHash);
READWRITE(sigTime);
READWRITE(vchSig);
}
bool CheckAndUpdate(int& nDos);
bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode);
void Relay();
uint256 GetHash(){
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
ss << vin;
ss << sigTime;
return ss.GetHash();
}
void swap(CMasternodePing& first, CMasternodePing& second) // nothrow
{
// enable ADL (not necessary in our case, but good practice)
using std::swap;
// by swapping the members of two classes,
// the two classes are effectively swapped
swap(first.vin, second.vin);
swap(first.blockHash, second.blockHash);
swap(first.sigTime, second.sigTime);
swap(first.vchSig, second.vchSig);
}
CMasternodePing& operator=(CMasternodePing from)
{
swap(*this, from);
return *this;
}
friend bool operator==(const CMasternodePing& a, const CMasternodePing& b)
{
return a.vin == b.vin && a.blockHash == b.blockHash;
}
friend bool operator!=(const CMasternodePing& a, const CMasternodePing& b)
{
return !(a == b);
}
};
//
// The Masternode Class. For managing the Darksend process. It contains the input of the 1000DRK, signature to prove
// it's the one who own that ip address and code for calculating the payment election.
@ -64,9 +129,7 @@ public:
CPubKey pubkey2;
std::vector<unsigned char> sig;
int activeState;
int64_t sigTime; //mnb message times
int64_t lastMnping;
int64_t lastTimeSeen;
int64_t sigTime; //mnb message time
int cacheInputAge;
int cacheInputAgeBlock;
bool unitTest;
@ -76,11 +139,12 @@ public:
int nScanningErrorCount;
int nLastScanningErrorBlockHeight;
int nVotedTimes;
CMasternodePing lastPing;
CMasternode();
CMasternode(const CMasternode& other);
CMasternode(const CMasternodeBroadcast& other);
CMasternode(CService newAddr, CTxIn newVin, CPubKey newPubkey, std::vector<unsigned char> newSig, int64_t newSigTime, CPubKey newPubkey2, int protocolVersionIn);
CMasternode(const CMasternodeBroadcast& mnb);
void swap(CMasternode& first, CMasternode& second) // nothrow
@ -97,8 +161,7 @@ public:
swap(first.sig, second.sig);
swap(first.activeState, second.activeState);
swap(first.sigTime, second.sigTime);
swap(first.lastMnping, second.lastMnping);
swap(first.lastTimeSeen, second.lastTimeSeen);
swap(first.lastPing, second.lastPing);
swap(first.cacheInputAge, second.cacheInputAge);
swap(first.cacheInputAgeBlock, second.cacheInputAgeBlock);
swap(first.unitTest, second.unitTest);
@ -138,10 +201,9 @@ public:
READWRITE(pubkey2);
READWRITE(sig);
READWRITE(sigTime);
READWRITE(lastTimeSeen);
READWRITE(protocolVersion);
READWRITE(activeState);
READWRITE(lastMnping);
READWRITE(lastPing);
READWRITE(cacheInputAge);
READWRITE(cacheInputAgeBlock);
READWRITE(unitTest);
@ -156,15 +218,6 @@ public:
void UpdateFromNewBroadcast(CMasternodeBroadcast& mnb);
void UpdateLastSeen(int64_t override=0)
{
if(override == 0){
lastTimeSeen = GetAdjustedTime();
} else {
lastTimeSeen = override;
}
}
inline uint64_t SliceHash(uint256& hash, int slice)
{
uint64_t n = 0;
@ -174,16 +227,23 @@ public:
void Check();
bool UpdatedWithin(int seconds)
bool IsBroadcastedWithin(int seconds)
{
// LogPrintf("UpdatedWithin %d, %d -- %d \n", GetAdjustedTime() , lastTimeSeen, (GetAdjustedTime() - lastTimeSeen) < seconds);
return (GetAdjustedTime() - sigTime) < seconds;
}
return (GetAdjustedTime() - lastTimeSeen) < seconds;
bool IsPingedWithin(int seconds, int64_t now = -1)
{
now == -1 ? now = GetAdjustedTime() : now;
return (lastPing == CMasternodePing())
? false
: now - lastPing.sigTime < seconds;
}
void Disable()
{
lastTimeSeen = 0;
sigTime = 0;
lastPing = CMasternodePing();
}
bool IsEnabled()
@ -229,12 +289,12 @@ class CMasternodeBroadcast : public CMasternode
public:
CMasternodeBroadcast();
CMasternodeBroadcast(CService newAddr, CTxIn newVin, CPubKey newPubkey, CPubKey newPubkey2, int protocolVersionIn);
CMasternodeBroadcast(const CMasternode& other);
CMasternodeBroadcast(const CMasternode& mn);
bool CheckAndUpdate(int& nDoS, bool fRequested);
bool CheckInputsAndAdd(int& nDos, bool fRequested);
bool CheckAndUpdate(int& nDoS);
bool CheckInputsAndAdd(int& nDos);
bool Sign(CKey& keyCollateralAddress);
void Relay(bool fRequested);
void Relay();
ADD_SERIALIZE_METHODS;
@ -246,8 +306,8 @@ public:
READWRITE(pubkey2);
READWRITE(sig);
READWRITE(sigTime);
READWRITE(lastTimeSeen);
READWRITE(protocolVersion);
READWRITE(lastPing);
}
uint256 GetHash(){
@ -259,43 +319,4 @@ public:
};
//
// The Masternode Ping Class : Contains a different serialize method for sending pings from masternodes throughout the network
//
class CMasternodePing
{
public:
CTxIn vin;
uint256 blockHash;
std::vector<unsigned char> vchSig;
int64_t sigTime; //mnb message times
//removed stop
CMasternodePing();
CMasternodePing(CTxIn& newVin);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(vin);
READWRITE(blockHash);
READWRITE(sigTime);
READWRITE(vchSig);
}
bool CheckAndUpdate(int& nDos);
bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode);
void Relay();
uint256 GetHash(){
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
ss << vin;
ss << sigTime;
return ss.GetHash();
}
};
#endif

View File

@ -12,8 +12,6 @@
#include <boost/lexical_cast.hpp>
#include <boost/filesystem.hpp>
CCriticalSection cs_process_message;
/** Masternode manager */
CMasternodeMan mnodeman;
@ -84,7 +82,7 @@ bool CMasternodeDB::Write(const CMasternodeMan& mnodemanToSave)
return true;
}
CMasternodeDB::ReadResult CMasternodeDB::Read(CMasternodeMan& mnodemanToLoad)
CMasternodeDB::ReadResult CMasternodeDB::Read(CMasternodeMan& mnodemanToLoad, bool fDryRun)
{
int64_t nStart = GetTimeMillis();
// open input file, and associate with CAutoFile
@ -159,9 +157,12 @@ CMasternodeDB::ReadResult CMasternodeDB::Read(CMasternodeMan& mnodemanToLoad)
return IncorrectFormat;
}
mnodemanToLoad.CheckAndRemove(); // clean out expired
LogPrintf("Loaded info from mncache.dat %dms\n", GetTimeMillis() - nStart);
LogPrintf(" %s\n", mnodemanToLoad.ToString());
LogPrintf("Masternode manager - cleaning....\n");
if(!fDryRun) mnodemanToLoad.CheckAndRemove(true);
LogPrintf("Masternode manager - result:\n");
LogPrintf(" %s\n", mnodemanToLoad.ToString());
return Ok;
}
@ -174,7 +175,7 @@ void DumpMasternodes()
CMasternodeMan tempMnodeman;
LogPrintf("Verifying mncache.dat format...\n");
CMasternodeDB::ReadResult readResult = mndb.Read(tempMnodeman);
CMasternodeDB::ReadResult readResult = mndb.Read(tempMnodeman, true);
// there was an error and it was not an error on file openning => do not proceed
if (readResult == CMasternodeDB::FileError)
LogPrintf("Missing masternode cache file - mncache.dat, will try to recreate\n");
@ -223,24 +224,22 @@ void CMasternodeMan::Check()
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
mn.Check();
// // if it matches our Masternode privkey, then we've been remotely activated
// if(mn.pubkey2 == activeMasternode.pubKeyMasternode && mn.protocolVersion == PROTOCOL_VERSION){
// activeMasternode.EnableHotColdMasterNode(mn.vin, mn.addr);
// }
}
}
void CMasternodeMan::CheckAndRemove()
void CMasternodeMan::CheckAndRemove(bool forceExpiredRemoval)
{
LOCK(cs);
Check();
//remove inactive
//remove inactive and outdated
vector<CMasternode>::iterator it = vMasternodes.begin();
while(it != vMasternodes.end()){
if((*it).activeState == CMasternode::MASTERNODE_REMOVE || (*it).activeState == CMasternode::MASTERNODE_VIN_SPENT || (*it).protocolVersion < nMasternodeMinProtocol){
if((*it).activeState == CMasternode::MASTERNODE_REMOVE ||
(*it).activeState == CMasternode::MASTERNODE_VIN_SPENT ||
(forceExpiredRemoval && (*it).activeState == CMasternode::MASTERNODE_EXPIRED) ||
(*it).protocolVersion < nMasternodeMinProtocol) {
if(fDebug) LogPrintf("CMasternodeMan: Removing inactive Masternode %s - %i now\n", (*it).addr.ToString().c_str(), size() - 1);
it = vMasternodes.erase(it);
} else {
@ -576,14 +575,13 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
if (strCommand == "mnb") { //Masternode Broadcast
CMasternodeBroadcast mnb;
bool fRequested; //specifically requested?
vRecv >> mnb >> fRequested;
vRecv >> mnb;
if(mapSeenMasternodeBroadcast.count(mnb.GetHash())) return; //seen
mapSeenMasternodeBroadcast[mnb.GetHash()] = mnb;
int nDoS = 0;
if(!mnb.CheckAndUpdate(nDoS, fRequested)){
if(!mnb.CheckAndUpdate(nDoS)){
if(nDoS > 0)
Misbehaving(pfrom->GetId(), nDoS);
@ -600,15 +598,13 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
return;
}
if(fDebug) LogPrintf("mnb - Got NEW Masternode entry %s\n", mnb.addr.ToString().c_str());
// make sure it's still unspent
// - this is checked later by .check() in many places and by ThreadCheckDarkSendPool()
if(mnb.CheckInputsAndAdd(nDoS, fRequested)) {
if(mnb.CheckInputsAndAdd(nDoS)) {
// use this as a peer
addrman.Add(CAddress(mnb.addr), pfrom->addr, 2*60*60);
} else {
LogPrintf("mnb - Rejected Masternode entry %s\n", mnb.addr.ToString().c_str());
LogPrintf("mnb - Rejected Masternode entry %s\n", mnb.addr.ToString());
if (nDoS > 0)
Misbehaving(pfrom->GetId(), nDoS);
@ -619,22 +615,22 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
CMasternodePing mnp;
vRecv >> mnp;
if(fDebug) LogPrintf("mnp - Masternode ping, vin: %s\n", mnp.vin.ToString());
if(mapSeenMasternodePing.count(mnp.GetHash())) return; //seen
mapSeenMasternodePing[mnp.GetHash()] = mnp;
int nDoS = 0;
if(mnp.CheckAndUpdate(nDoS))
{
//successful, we're done
if(mnp.CheckAndUpdate(nDoS)) return;
if(nDoS > 0) {
// if anything significant failed, mark that node and return
Misbehaving(pfrom->GetId(), nDoS);
return;
} else {
//failure
if(nDoS > 0)
Misbehaving(pfrom->GetId(), nDoS);
}
if(fDebug) LogPrintf("mnp - Couldn't find Masternode entry %s\n", mnp.vin.ToString().c_str());
// we wasn't able to accept mnp but nothing significant happened,
// we might just have to ask for a masternode entry once
std::map<COutPoint, int64_t>::iterator i = mWeAskedForMasternodeListEntry.find(mnp.vin.prevout);
if (i != mWeAskedForMasternodeListEntry.end())
{
@ -644,7 +640,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
// ask for the mnb info once from the node that sent mnp
LogPrintf("mnp - Asking source node for missing entry %s\n", mnp.vin.ToString().c_str());
LogPrintf("mnp - Asking source node for missing entry, vin: %s\n", mnp.vin.ToString());
pfrom->PushMessage("dseg", mnp.vin);
int64_t askAgain = GetTime() + MASTERNODE_MIN_MNP_SECONDS;
mWeAskedForMasternodeListEntry[mnp.vin.prevout] = askAgain;
@ -677,27 +673,24 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
if(mn.addr.IsRFC1918()) continue; //local network
bool fRequested = true;
if(mn.IsEnabled()) {
if(fDebug) LogPrintf("dseg - Sending Masternode entry - %s \n", mn.addr.ToString().c_str());
if(vin == CTxIn()){
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << CMasternodeBroadcast(mn);
ss << fRequested;
pfrom->PushMessage("mnb", ss);
} else if (vin == mn.vin) {
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << CMasternodeBroadcast(mn);
ss << fRequested;
pfrom->PushMessage("mnb", ss);
LogPrintf("dseg - Sent 1 Masternode entries to %s\n", pfrom->addr.ToString().c_str());
return;
}
i++;
}
i++;
}
LogPrintf("dseg - Sent %d Masternode entries to %s\n", i, pfrom->addr.ToString().c_str());

View File

@ -49,7 +49,7 @@ public:
CMasternodeDB();
bool Write(const CMasternodeMan &mnodemanToSave);
ReadResult Read(CMasternodeMan& mnodemanToLoad);
ReadResult Read(CMasternodeMan& mnodemanToLoad, bool fDryRun = false);
};
class CMasternodeMan
@ -58,6 +58,9 @@ private:
// critical section to protect the inner data structures
mutable CCriticalSection cs;
// critical section to protect the inner data structures specifically on messaging
mutable CCriticalSection cs_process_message;
// map to hold all MNs
std::vector<CMasternode> vMasternodes;
// who's asked for the Masternode list and the last time
@ -93,7 +96,7 @@ public:
void Check();
/// Check all Masternodes and remove inactive
void CheckAndRemove();
void CheckAndRemove(bool forceExpiredRemoval = false);
/// Clear Masternode vector
void Clear();

View File

@ -19,7 +19,6 @@
#ifdef ENABLE_WALLET
#include "wallet.h"
#endif
#include "masternodeman.h"
#include "masternode-payments.h"
#include <boost/thread.hpp>

View File

@ -199,21 +199,13 @@ Value masternode(const Array& params, bool fHelp)
}
}
if(activeMasternode.status != MASTERNODE_REMOTELY_ENABLED && activeMasternode.status != MASTERNODE_IS_CAPABLE){
activeMasternode.status = MASTERNODE_NOT_PROCESSED; // TODO: consider better way
std::string errorMessage;
if(activeMasternode.status != MASTERNODE_STARTED){
activeMasternode.status = MASTERNODE_INITIAL; // TODO: consider better way
activeMasternode.ManageStatus();
pwalletMain->Lock();
}
if(activeMasternode.status == MASTERNODE_REMOTELY_ENABLED) return "masternode started remotely";
if(activeMasternode.status == MASTERNODE_INPUT_TOO_NEW) return "masternode input must have at least 15 confirmations";
if(activeMasternode.status == MASTERNODE_STOPPED) return "masternode is stopped";
if(activeMasternode.status == MASTERNODE_IS_CAPABLE) return "successfully started masternode";
if(activeMasternode.status == MASTERNODE_NOT_CAPABLE) return "not capable masternode: " + activeMasternode.notCapableReason;
if(activeMasternode.status == MASTERNODE_SYNC_IN_PROCESS) return "sync in process. Must wait until client is synced to start.";
return "unknown";
return activeMasternode.GetStatus();
}
if (strCommand == "start-alias")
@ -330,12 +322,7 @@ Value masternode(const Array& params, bool fHelp)
if (strCommand == "debug")
{
if(activeMasternode.status == MASTERNODE_REMOTELY_ENABLED) return "masternode started remotely";
if(activeMasternode.status == MASTERNODE_INPUT_TOO_NEW) return "masternode input must have at least 15 confirmations";
if(activeMasternode.status == MASTERNODE_IS_CAPABLE) return "successfully started masternode";
if(activeMasternode.status == MASTERNODE_STOPPED) return "masternode is stopped";
if(activeMasternode.status == MASTERNODE_NOT_CAPABLE) return "not capable masternode: " + activeMasternode.notCapableReason;
if(activeMasternode.status == MASTERNODE_SYNC_IN_PROCESS) return "sync in process. Must wait until client is synced to start.";
if(activeMasternode.status != MASTERNODE_INITIAL) return activeMasternode.GetStatus();
CTxIn vin = CTxIn();
CPubKey pubkey = CScript();
@ -369,8 +356,10 @@ Value masternode(const Array& params, bool fHelp)
obj.push_back(Pair("protocol", (int64_t)winner->protocolVersion));
obj.push_back(Pair("vin", winner->vin.prevout.hash.ToString().c_str()));
obj.push_back(Pair("pubkey", address2.ToString().c_str()));
obj.push_back(Pair("lastseen", (int64_t)winner->lastTimeSeen));
obj.push_back(Pair("activeseconds", (int64_t)(winner->lastTimeSeen - winner->sigTime)));
obj.push_back(Pair("lastseen", (winner->lastPing == CMasternodePing()) ? winner->sigTime :
(int64_t)winner->lastPing.sigTime));
obj.push_back(Pair("activeseconds", (winner->lastPing == CMasternodePing()) ? 0 :
(int64_t)(winner->lastPing.sigTime - winner->sigTime)));
return obj;
}
@ -498,6 +487,7 @@ Value masternodelist(const Array& params, bool fHelp)
" additional matches in some modes are also available\n"
"\nAvailable modes:\n"
" activeseconds - Print number of seconds masternode recognized by the network as enabled\n"
" (since latest issued \"masternode start/start-many/start-alias\")\n"
" full - Print info in format 'status protocol pubkey IP lastseen activeseconds lastpaid'\n"
" (can be additionally filtered, partial match)\n"
" lastseen - Print timestamp of when a masternode was last seen on the network\n"
@ -526,7 +516,7 @@ Value masternodelist(const Array& params, bool fHelp)
std::string strVin = mn.vin.prevout.ToStringShort();
if (strMode == "activeseconds") {
if(strFilter !="" && strVin.find(strFilter) == string::npos) continue;
obj.push_back(Pair(strVin, (int64_t)(mn.lastTimeSeen - mn.sigTime)));
obj.push_back(Pair(strVin, (int64_t)(mn.lastPing.sigTime - mn.sigTime)));
} else if (strMode == "full") {
CScript pubkey;
pubkey = GetScriptForDestination(mn.pubkey.GetID());
@ -543,8 +533,8 @@ Value masternodelist(const Array& params, bool fHelp)
mn.protocolVersion << " " <<
address2.ToString() << " " <<
mn.addr.ToString() << " " <<
mn.lastTimeSeen << " " << setw(8) <<
(mn.lastTimeSeen - mn.sigTime) << " " <<
mn.lastPing.sigTime << " " << setw(8) <<
(mn.lastPing.sigTime - mn.sigTime) << " " <<
mn.GetLastPaid();
std::string output = stringStream.str();
stringStream << " " << strVin;
@ -553,7 +543,7 @@ Value masternodelist(const Array& params, bool fHelp)
obj.push_back(Pair(addrStream.str(), output));
} else if (strMode == "lastseen") {
if(strFilter !="" && strVin.find(strFilter) == string::npos) continue;
obj.push_back(Pair(strVin, (int64_t)mn.lastTimeSeen));
obj.push_back(Pair(strVin, (int64_t)mn.lastPing.sigTime));
} else if (strMode == "protocol") {
if(strFilter !="" && strFilter != boost::lexical_cast<std::string>(mn.protocolVersion) &&
strVin.find(strFilter) == string::npos) continue;

View File

@ -10,7 +10,7 @@
* network protocol versioning
*/
static const int PROTOCOL_VERSION = 70089;
static const int PROTOCOL_VERSION = 70090;
//! initial proto version, to be increased after version/verack negotiation
static const int INIT_PROTO_VERSION = 209;
@ -22,16 +22,16 @@ static const int GETHEADERS_VERSION = 70077;
static const int MIN_PEER_PROTO_VERSION = 70066;
//! minimum peer version accepted by DarksendPool
static const int MIN_POOL_PEER_PROTO_VERSION = 70089;
static const int MIN_POOL_PEER_PROTO_VERSION = 70090;
//! minimum peer version for masternode budgets
static const int MIN_BUDGET_PEER_PROTO_VERSION = 70089;
static const int MIN_BUDGET_PEER_PROTO_VERSION = 70090;
//! minimum peer version that can receive masternode payments
// V1 - Last protocol version before update
// V2 - Newest protocol version
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1 = 70066;
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70089;
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70090;
//! nTime field added to CAddress, starting with this version;
//! if possible, avoid requesting addresses nodes older than this