diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp index 2850f57a95..ad0c88f823 100644 --- a/src/activemasternode.cpp +++ b/src/activemasternode.cpp @@ -4,6 +4,7 @@ #include "masternodeman.h" #include "masternode.h" #include "masternodeconfig.h" +#include "spork.h" // // Bootup the Masternode, look for a 1000DRK input and register on the network @@ -175,6 +176,37 @@ bool CActiveMasternode::SendMasternodePing(std::string& errorMessage) { mnodeman.mapSeenMasternodePing.insert(make_pair(mnp.GetHash(), mnp)); mnp.Relay(); + /* + * IT'S SAFE TO REMOVE THIS IN FURTHER VERSIONS + * AFTER MIGRATION TO V12 IS DONE + */ + + if(IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) return true; + // for migration purposes ping our node on old masternodes network too + std::string retErrorMessage; + std::vector vchMasterNodeSignature; + int64_t masterNodeSignatureTime = GetAdjustedTime(); + + std::string strMessage = service.ToString() + boost::lexical_cast(masterNodeSignatureTime) + boost::lexical_cast(0); + + if(!darkSendSigner.SignMessage(strMessage, retErrorMessage, vchMasterNodeSignature, keyMasternode)) { + errorMessage = "dseep sign message failed: " + retErrorMessage; + return false; + } + + if(!darkSendSigner.VerifyMessage(pubKeyMasternode, vchMasterNodeSignature, strMessage, retErrorMessage)) { + errorMessage = "dseep verify message failed: " + retErrorMessage; + return false; + } + + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + pnode->PushMessage("dseep", vin, vchMasterNodeSignature, masterNodeSignatureTime, 0); + + /* + * END OF "REMOVE" + */ + return true; } else @@ -265,6 +297,44 @@ bool CActiveMasternode::Register(CTxIn vin, CService service, CKey keyCollateral LogPrintf("CActiveMasternode::Register() - RelayElectionEntry vin = %s\n", vin.ToString()); mnb.Relay(); + /* + * IT'S SAFE TO REMOVE THIS IN FURTHER VERSIONS + * AFTER MIGRATION TO V12 IS DONE + */ + + if(IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) return true; + // for migration purposes inject our node in old masternodes' list too + std::string retErrorMessage; + std::vector vchMasterNodeSignature; + int64_t masterNodeSignatureTime = GetAdjustedTime(); + std::string donationAddress = ""; + int donationPercantage = 0; + + std::string vchPubKey(pubKeyCollateralAddress.begin(), pubKeyCollateralAddress.end()); + std::string vchPubKey2(pubKeyMasternode.begin(), pubKeyMasternode.end()); + + std::string strMessage = service.ToString() + boost::lexical_cast(masterNodeSignatureTime) + vchPubKey + vchPubKey2 + boost::lexical_cast(PROTOCOL_VERSION) + donationAddress + boost::lexical_cast(donationPercantage); + + if(!darkSendSigner.SignMessage(strMessage, retErrorMessage, vchMasterNodeSignature, keyCollateralAddress)) { + errorMessage = "dsee sign message failed: " + retErrorMessage; + LogPrintf("CActiveMasternode::Register() - Error: %s\n", errorMessage.c_str()); + return false; + } + + if(!darkSendSigner.VerifyMessage(pubKeyCollateralAddress, vchMasterNodeSignature, strMessage, retErrorMessage)) { + errorMessage = "dsee verify message failed: " + retErrorMessage; + LogPrintf("CActiveMasternode::Register() - Error: %s\n", errorMessage.c_str()); + return false; + } + + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + pnode->PushMessage("dsee", vin, service, vchMasterNodeSignature, masterNodeSignatureTime, pubKeyCollateralAddress, pubKeyMasternode, -1, -1, masterNodeSignatureTime, PROTOCOL_VERSION, donationAddress, donationPercantage); + + /* + * END OF "REMOVE" + */ + return true; } diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index 3f8dc85540..7f6b224f6b 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -771,6 +771,262 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData LogPrintf("dseg - Sent %d Masternode entries to %s\n", i, pfrom->addr.ToString()); } + /* + * IT'S SAFE TO REMOVE THIS IN FURTHER VERSIONS + * AFTER MIGRATION TO V12 IS DONE + */ + + // Light version for OLD MASSTERNODES - fake pings, no self-activation + else if (strCommand == "dsee") { //DarkSend Election Entry + + if(IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) return; + + CTxIn vin; + CService addr; + CPubKey pubkey; + CPubKey pubkey2; + vector vchSig; + int64_t sigTime; + int count; + int current; + int64_t lastUpdated; + int protocolVersion; + CScript donationAddress; + int donationPercentage; + std::string strMessage; + + vRecv >> vin >> addr >> vchSig >> sigTime >> pubkey >> pubkey2 >> count >> current >> lastUpdated >> protocolVersion >> donationAddress >> donationPercentage; + + // make sure signature isn't in the future (past is OK) + if (sigTime > GetAdjustedTime() + 60 * 60) { + LogPrintf("dsee - Signature rejected, too far into the future %s\n", vin.ToString().c_str()); + return; + } + + bool isLocal = addr.IsRFC1918() || addr.IsLocal(); + if(Params().NetworkID() == CBaseChainParams::REGTEST) isLocal = false; + + std::string vchPubKey(pubkey.begin(), pubkey.end()); + std::string vchPubKey2(pubkey2.begin(), pubkey2.end()); + + strMessage = addr.ToString() + boost::lexical_cast(sigTime) + vchPubKey + vchPubKey2 + boost::lexical_cast(protocolVersion) + donationAddress.ToString() + boost::lexical_cast(donationPercentage); + + if(protocolVersion < masternodePayments.GetMinMasternodePaymentsProto()) { + LogPrintf("dsee - ignoring outdated Masternode %s protocol version %d < %d\n", vin.ToString().c_str(), protocolVersion, masternodePayments.GetMinMasternodePaymentsProto()); + return; + } + + int nDos = 0; + CScript pubkeyScript; + pubkeyScript = GetScriptForDestination(pubkey.GetID()); + + if(pubkeyScript.size() != 25) { + LogPrintf("dsee - pubkey the wrong size\n"); + nDos = 100; + return; + } + + CScript pubkeyScript2; + pubkeyScript2 = GetScriptForDestination(pubkey2.GetID()); + + if(pubkeyScript2.size() != 25) { + LogPrintf("dsee - pubkey2 the wrong size\n"); + nDos = 100; + return; + } + + if(!vin.scriptSig.empty()) { + LogPrintf("dsee - Ignore Not Empty ScriptSig %s\n",vin.ToString()); + return; + } + + std::string errorMessage = ""; + if(!darkSendSigner.VerifyMessage(pubkey, vchSig, strMessage, errorMessage)){ + LogPrintf("dsee - Got bad Masternode address signature\n"); + Misbehaving(pfrom->GetId(), 100); + return; + } + + if(Params().NetworkID() == CBaseChainParams::MAIN){ + if(addr.GetPort() != 9999) return; + } else if(addr.GetPort() == 9999) return; + + //search existing Masternode list, this is where we update existing Masternodes with new dsee broadcasts + CMasternode* pmn = this->Find(vin); + if(pmn != NULL) + { + // count == -1 when it's a new entry + // e.g. We don't want the entry relayed/time updated when we're syncing the list + // mn.pubkey = pubkey, IsVinAssociatedWithPubkey is validated once below, + // after that they just need to match + if(count == -1 && pmn->pubkey == pubkey && (pmn->lastPing.sigTime < GetTime() - MASTERNODE_MIN_MNB_SECONDS)){ + if(pmn->sigTime < sigTime){ //take the newest entry + LogPrintf("dsee - Got updated entry for %s\n", addr.ToString().c_str()); + pmn->pubkey2 = pubkey2; + pmn->sigTime = sigTime; + pmn->sig = vchSig; + pmn->protocolVersion = protocolVersion; + pmn->addr = addr; + //fake ping + pmn->lastPing = CMasternodePing(vin); + pmn->Check(); + if(pmn->IsEnabled()) { + TRY_LOCK(cs_vNodes, lockNodes); + if(!lockNodes) return; + BOOST_FOREACH(CNode* pnode, vNodes) + if(pnode->nVersion >= masternodePayments.GetMinMasternodePaymentsProto()) + pnode->PushMessage("dsee", vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated, protocolVersion, donationAddress, donationPercentage); + } + } + } + + return; + } + + // make sure the vout that was signed is related to the transaction that spawned the Masternode + // - this is expensive, so it's only done once per Masternode + if(!darkSendSigner.IsVinAssociatedWithPubkey(vin, pubkey)) { + LogPrintf("dsee - Got mismatched pubkey and vin\n"); + Misbehaving(pfrom->GetId(), 100); + return; + } + + if(fDebug) LogPrintf("dsee - Got NEW OLD Masternode entry %s\n", addr.ToString().c_str()); + + // make sure it's still unspent + // - this is checked later by .check() in many places and by ThreadCheckDarkSendPool() + + CValidationState state; + CMutableTransaction tx = CMutableTransaction(); + CTxOut vout = CTxOut(999.99*COIN, darkSendPool.collateralPubKey); + tx.vin.push_back(vin); + tx.vout.push_back(vout); + if(AcceptableInputs(mempool, state, CTransaction(tx), false, NULL)){ + if(fDebug) LogPrintf("dsee - Accepted OLD Masternode entry %i %i\n", count, current); + + if(GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS){ + LogPrintf("dsee - Input must have least %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS); + Misbehaving(pfrom->GetId(), 20); + return; + } + + // verify that sig time is legit in past + // should be at least not earlier than block when 1000 DASH tx got MASTERNODE_MIN_CONFIRMATIONS + uint256 hashBlock = 0; + CTransaction tx2; + GetTransaction(vin.prevout.hash, tx2, hashBlock, true); + BlockMap::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) + { + CBlockIndex* pMNIndex = (*mi).second; // block for 1000 DASH tx -> 1 confirmation + CBlockIndex* pConfIndex = chainActive[pMNIndex->nHeight + MASTERNODE_MIN_CONFIRMATIONS - 1]; // block where tx got MASTERNODE_MIN_CONFIRMATIONS + if(pConfIndex->GetBlockTime() > sigTime) + { + LogPrintf("mnb - Bad sigTime %d for Masternode %20s %105s (%i conf block is at %d)\n", + sigTime, addr.ToString(), vin.ToString(), MASTERNODE_MIN_CONFIRMATIONS, pConfIndex->GetBlockTime()); + return; + } + } + + // use this as a peer + addrman.Add(CAddress(addr), pfrom->addr, 2*60*60); + + // add our Masternode + CMasternode mn = CMasternode(); + mn.addr = addr; + mn.vin = vin; + mn.pubkey = pubkey; + mn.sig = vchSig; + mn.sigTime = sigTime; + mn.pubkey2 = pubkey2; + mn.protocolVersion = protocolVersion; + // fake ping + mn.lastPing = CMasternodePing(vin); + Add(mn); + mn.Check(true); + if(mn.IsEnabled()) { + TRY_LOCK(cs_vNodes, lockNodes); + if(!lockNodes) return; + BOOST_FOREACH(CNode* pnode, vNodes) + if(pnode->nVersion >= masternodePayments.GetMinMasternodePaymentsProto()) + pnode->PushMessage("dsee", vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated, protocolVersion, donationAddress, donationPercentage); + } + } else { + LogPrintf("dsee - Rejected Masternode entry %s\n", addr.ToString().c_str()); + + int nDoS = 0; + if (state.IsInvalid(nDoS)) + { + LogPrintf("dsee - %s from %s %s was not accepted into the memory pool\n", tx.GetHash().ToString().c_str(), + pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str()); + if (nDoS > 0) + Misbehaving(pfrom->GetId(), nDoS); + } + } + } + + else if (strCommand == "dseep") { //DarkSend Election Entry Ping + + if(IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) return; + + CTxIn vin; + vector vchSig; + int64_t sigTime; + bool stop; + vRecv >> vin >> vchSig >> sigTime >> stop; + + //LogPrintf("dseep - Received: vin: %s sigTime: %lld stop: %s\n", vin.ToString().c_str(), sigTime, stop ? "true" : "false"); + + if (sigTime > GetAdjustedTime() + 60 * 60) { + LogPrintf("dseep - Signature rejected, too far into the future %s\n", vin.ToString().c_str()); + return; + } + + if (sigTime <= GetAdjustedTime() - 60 * 60) { + LogPrintf("dseep - Signature rejected, too far into the past %s - %d %d \n", vin.ToString().c_str(), sigTime, GetAdjustedTime()); + return; + } + + // see if we have this Masternode + CMasternode* pmn = this->Find(vin); + if(pmn != NULL && pmn->protocolVersion >= masternodePayments.GetMinMasternodePaymentsProto()) + { + // LogPrintf("dseep - Found corresponding mn for vin: %s\n", vin.ToString().c_str()); + // take this only if it's newer + if(sigTime - pmn->lastPing.sigTime > MASTERNODE_MIN_MNP_SECONDS) + { + std::string strMessage = pmn->addr.ToString() + boost::lexical_cast(sigTime) + boost::lexical_cast(stop); + + std::string errorMessage = ""; + if(!darkSendSigner.VerifyMessage(pmn->pubkey2, vchSig, strMessage, errorMessage)) + { + LogPrintf("dseep - Got bad Masternode address signature %s \n", vin.ToString().c_str()); + //Misbehaving(pfrom->GetId(), 100); + return; + } + + // fake ping + pmn->lastPing = CMasternodePing(); + pmn->Check(); + if(pmn->IsEnabled()) { + TRY_LOCK(cs_vNodes, lockNodes); + if(!lockNodes) return; + BOOST_FOREACH(CNode* pnode, vNodes) + if(pnode->nVersion >= masternodePayments.GetMinMasternodePaymentsProto()) + pnode->PushMessage("dseep", vin, vchSig, sigTime, stop); + } + } + return; + } + + if(fDebug) LogPrintf("dseep - Couldn't find Masternode entry %s\n", vin.ToString().c_str()); + + AskForMN(pfrom, vin); + } + + /* + * END OF "REMOVE" + */ }