Skip to content

Commit

Permalink
Backport masternodebroadcast to v0.12.0.x
Browse files Browse the repository at this point in the history
see 40f0d1f and c96284a for more info
  • Loading branch information
UdjinM6 committed Jul 7, 2016
1 parent 88f3370 commit 256e02f
Show file tree
Hide file tree
Showing 9 changed files with 437 additions and 93 deletions.
61 changes: 29 additions & 32 deletions src/activemasternode.cpp
Expand Up @@ -113,12 +113,17 @@ void CActiveMasternode::ManageStatus()
return;
}

if(!Register(vin, service, keyCollateralAddress, pubKeyCollateralAddress, keyMasternode, pubKeyMasternode, errorMessage)) {
notCapableReason = "Error on Register: " + errorMessage;
CMasternodeBroadcast mnb;
if(!CreateBroadcast(vin, service, keyCollateralAddress, pubKeyCollateralAddress, keyMasternode, pubKeyMasternode, errorMessage, mnb)) {
notCapableReason = "Error on CreateBroadcast: " + errorMessage;
LogPrintf("Register::ManageStatus() - %s\n", notCapableReason);
return;
}

//send to all peers
LogPrintf("CActiveMasternode::ManageStatus() - Relay broadcast vin = %s\n", vin.ToString());
mnb.Relay();

LogPrintf("CActiveMasternode::ManageStatus() - Is capable master node!\n");
status = ACTIVE_MASTERNODE_STARTED;

Expand Down Expand Up @@ -203,84 +208,71 @@ bool CActiveMasternode::SendMasternodePing(std::string& errorMessage) {

}

bool CActiveMasternode::Register(std::string strService, std::string strKeyMasternode, std::string strTxHash, std::string strOutputIndex, std::string& errorMessage) {
bool CActiveMasternode::CreateBroadcast(std::string strService, std::string strKeyMasternode, std::string strTxHash, std::string strOutputIndex, std::string& errorMessage, CMasternodeBroadcast &mnb, bool fOffline) {
CTxIn vin;
CPubKey pubKeyCollateralAddress;
CKey keyCollateralAddress;
CPubKey pubKeyMasternode;
CKey keyMasternode;

//need correct blocks to send ping
if(!masternodeSync.IsBlockchainSynced()) {
errorMessage = GetStatus();
LogPrintf("CActiveMasternode::Register() - %s\n", errorMessage);
if(!fOffline && !masternodeSync.IsBlockchainSynced()) {
errorMessage = "Sync in progress. Must wait until sync is complete to start Masternode";
LogPrintf("CActiveMasternode::CreateBroadcast() - %s\n", errorMessage);
return false;
}

if(!darkSendSigner.SetKey(strKeyMasternode, errorMessage, keyMasternode, pubKeyMasternode))
{
errorMessage = strprintf("Can't find keys for masternode %s - %s", strService, errorMessage);
LogPrintf("CActiveMasternode::Register() - %s\n", errorMessage);
LogPrintf("CActiveMasternode::CreateBroadcast() - %s\n", errorMessage);
return false;
}

if(!GetMasterNodeVin(vin, pubKeyCollateralAddress, keyCollateralAddress, strTxHash, strOutputIndex)) {
errorMessage = strprintf("Could not allocate vin %s:%s for masternode %s", strTxHash, strOutputIndex, strService);
LogPrintf("CActiveMasternode::Register() - %s\n", errorMessage);
LogPrintf("CActiveMasternode::CreateBroadcast() - %s\n", errorMessage);
return false;
}

CService service = CService(strService);
if(Params().NetworkID() == CBaseChainParams::MAIN) {
if(service.GetPort() != 9999) {
errorMessage = strprintf("Invalid port %u for masternode %s - only 9999 is supported on mainnet.", service.GetPort(), strService);
LogPrintf("CActiveMasternode::Register() - %s\n", errorMessage);
LogPrintf("CActiveMasternode::CreateBroadcast() - %s\n", errorMessage);
return false;
}
} else if(service.GetPort() == 9999) {
errorMessage = strprintf("Invalid port %u for masternode %s - 9999 is only supported on mainnet.", service.GetPort(), strService);
LogPrintf("CActiveMasternode::Register() - %s\n", errorMessage);
LogPrintf("CActiveMasternode::CreateBroadcast() - %s\n", errorMessage);
return false;
}

addrman.Add(CAddress(service), CNetAddr("127.0.0.1"), 2*60*60);

return Register(vin, CService(strService), keyCollateralAddress, pubKeyCollateralAddress, keyMasternode, pubKeyMasternode, errorMessage);
return CreateBroadcast(vin, CService(strService), keyCollateralAddress, pubKeyCollateralAddress, keyMasternode, pubKeyMasternode, errorMessage, mnb);
}

bool CActiveMasternode::Register(CTxIn vin, CService service, CKey keyCollateralAddress, CPubKey pubKeyCollateralAddress, CKey keyMasternode, CPubKey pubKeyMasternode, std::string &errorMessage) {
CMasternodeBroadcast mnb;
bool CActiveMasternode::CreateBroadcast(CTxIn vin, CService service, CKey keyCollateralAddress, CPubKey pubKeyCollateralAddress, CKey keyMasternode, CPubKey pubKeyMasternode, std::string &errorMessage, CMasternodeBroadcast &mnb) {
// wait for reindex and/or import to finish
if (fImporting || fReindex) return false;

CMasternodePing mnp(vin);
if(!mnp.Sign(keyMasternode, pubKeyMasternode)){
errorMessage = strprintf("Failed to sign ping, vin: %s", vin.ToString());
LogPrintf("CActiveMasternode::Register() - %s\n", errorMessage);
LogPrintf("CActiveMasternode::CreateBroadcast() - %s\n", errorMessage);
mnb = CMasternodeBroadcast();
return false;
}
mnodeman.mapSeenMasternodePing.insert(make_pair(mnp.GetHash(), mnp));

LogPrintf("CActiveMasternode::Register() - Adding to Masternode list\n service: %s\n vin: %s\n", service.ToString(), vin.ToString());
mnb = CMasternodeBroadcast(service, vin, pubKeyCollateralAddress, pubKeyMasternode, PROTOCOL_VERSION);
mnb.lastPing = mnp;
if(!mnb.Sign(keyCollateralAddress)){
errorMessage = strprintf("Failed to sign broadcast, vin: %s", vin.ToString());
LogPrintf("CActiveMasternode::Register() - %s\n", errorMessage);
LogPrintf("CActiveMasternode::CreateBroadcast() - %s\n", errorMessage);
mnb = CMasternodeBroadcast();
return false;
}
mnodeman.mapSeenMasternodeBroadcast.insert(make_pair(mnb.GetHash(), mnb));
masternodeSync.AddedMasternodeList(mnb.GetHash());

CMasternode* pmn = mnodeman.Find(vin);
if(pmn == NULL)
{
CMasternode mn(mnb);
mnodeman.Add(mn);
} else {
pmn->UpdateFromNewBroadcast(mnb);
}

//send to all peers
LogPrintf("CActiveMasternode::Register() - RelayElectionEntry vin = %s\n", vin.ToString());
mnb.Relay();

return true;
}
Expand All @@ -290,6 +282,9 @@ bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secr
}

bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey, std::string strTxHash, std::string strOutputIndex) {
// wait for reindex and/or import to finish
if (fImporting || fReindex) return false;

// Find possible candidates
TRY_LOCK(pwalletMain->cs_wallet, fWallet);
if(!fWallet) return false;
Expand Down Expand Up @@ -332,6 +327,8 @@ bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secr

// Extract Masternode vin information from output
bool CActiveMasternode::GetVinFromOutput(COutput out, CTxIn& vin, CPubKey& pubkey, CKey& secretKey) {
// wait for reindex and/or import to finish
if (fImporting || fReindex) return false;

CScript pubScript;

Expand Down
8 changes: 4 additions & 4 deletions src/activemasternode.h
Expand Up @@ -29,8 +29,8 @@ class CActiveMasternode
/// 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 &errorMessage);
/// Create Masternode broadcast, needs to be relayed manually after that
bool CreateBroadcast(CTxIn vin, CService service, CKey key, CPubKey pubKey, CKey keyMasternode, CPubKey pubKeyMasternode, std::string &errorMessage, CMasternodeBroadcast &mnb);

/// Get 1000DRK input that can be used for the Masternode
bool GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey, std::string strTxHash, std::string strOutputIndex);
Expand All @@ -57,8 +57,8 @@ class CActiveMasternode
void ManageStatus();
std::string GetStatus();

/// Register remote Masternode
bool Register(std::string strService, std::string strKey, std::string strTxHash, std::string strOutputIndex, std::string& errorMessage);
/// Create Masternode broadcast, needs to be relayed manually after that
bool CreateBroadcast(std::string strService, std::string strKey, std::string strTxHash, std::string strOutputIndex, std::string& errorMessage, CMasternodeBroadcast &mnb, bool fOffline = false);

/// Get 1000DRK input that can be used for the Masternode
bool GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey);
Expand Down
74 changes: 54 additions & 20 deletions src/masternode.cpp
Expand Up @@ -376,6 +376,10 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
return false;
}

// incorrect ping or its sigTime
if(lastPing == CMasternodePing() || !lastPing.CheckAndUpdate(nDos, false, true))
return false;

std::string strMessage;
std::string errorMessage = "";

Expand Down Expand Up @@ -436,18 +440,20 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
CMasternode* pmn = mnodeman.Find(vin);

// no such masternode, nothing to update
if(pmn == NULL) return true ;
else {
// this broadcast older than we have, it's bad.
if(pmn->sigTime > sigTime) {
LogPrintf("mnb - Bad sigTime %d for Masternode %20s %105s (existing broadcast is at %d)\n",
sigTime, addr.ToString(), vin.ToString(), pmn->sigTime);
return false;
}
// masternode is not enabled yet/already, nothing to update
if(!pmn->IsEnabled()) return true;
if(pmn == NULL) return true;

// this broadcast is older or equal than the one that we already have - it's bad and should never happen
// unless someone is doing something fishy
// (mapSeenMasternodeBroadcast in CMasternodeMan::ProcessMessage should filter legit duplicates)
if(pmn->sigTime >= sigTime) {
LogPrintf("CMasternodeBroadcast::CheckAndUpdate - Bad sigTime %d for Masternode %20s %105s (existing broadcast is at %d)\n",
sigTime, addr.ToString(), vin.ToString(), pmn->sigTime);
return false;
}

// masternode is not enabled yet/already, nothing to update
if(!pmn->IsEnabled()) return true;

// 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)) {
Expand All @@ -470,6 +476,10 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS)
if(fMasterNode && vin.prevout == activeMasternode.vin.prevout && pubkey2 == activeMasternode.pubKeyMasternode)
return true;

// incorrect ping or its sigTime
if(lastPing == CMasternodePing() || !lastPing.CheckAndUpdate(nDoS, false, true))
return false;

// search existing Masternode list
CMasternode* pmn = mnodeman.Find(vin);

Expand Down Expand Up @@ -569,8 +579,20 @@ bool CMasternodeBroadcast::Sign(CKey& keyCollateralAddress)
return false;
}

return true;
}

bool CMasternodeBroadcast::VerifySignature()
{
std::string errorMessage;

std::string vchPubKey(pubkey.begin(), pubkey.end());
std::string vchPubKey2(pubkey2.begin(), pubkey2.end());

std::string strMessage = addr.ToString() + boost::lexical_cast<std::string>(sigTime) + vchPubKey + vchPubKey2 + boost::lexical_cast<std::string>(protocolVersion);

if(!darkSendSigner.VerifyMessage(pubkey, sig, strMessage, errorMessage)) {
LogPrintf("CMasternodeBroadcast::Sign() - Error: %s\n", errorMessage);
LogPrintf("CMasternodeBroadcast::VerifySignature() - Error: %s\n", errorMessage);
return false;
}

Expand Down Expand Up @@ -615,7 +637,20 @@ bool CMasternodePing::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
return true;
}

bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled)
bool CMasternodePing::VerifySignature(CPubKey& pubKeyMasternode, int &nDos) {
std::string strMessage = vin.ToString() + blockHash.ToString() + boost::lexical_cast<std::string>(sigTime);
std::string errorMessage = "";

if(!darkSendSigner.VerifyMessage(pubKeyMasternode, vchSig, strMessage, errorMessage))
{
LogPrintf("CMasternodePing::VerifySignature - Got bad Masternode ping signature %s Error: %s\n", vin.ToString(), errorMessage);
nDos = 33;
return false;
}
return true;
}

bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled, bool fCheckSigTimeOnly)
{
if (sigTime > GetAdjustedTime() + 60 * 60) {
LogPrintf("CMasternodePing::CheckAndUpdate - Signature rejected, too far into the future %s\n", vin.ToString());
Expand All @@ -629,6 +664,12 @@ bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled)
return false;
}

if(fCheckSigTimeOnly) {
CMasternode* pmn = mnodeman.Find(vin);
if(pmn) return VerifySignature(pmn->pubkey2, nDos);
return true;
}

LogPrint("masternode", "CMasternodePing::CheckAndUpdate - New Ping - %s - %s - %lli\n", GetHash().ToString(), blockHash.ToString(), sigTime);

// see if we have this Masternode
Expand All @@ -642,15 +683,8 @@ bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled)
// 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("CMasternodePing::CheckAndUpdate - Got bad Masternode address signature %s\n", vin.ToString());
nDos = 33;
if(!VerifySignature(pmn->pubkey2, nDos))
return false;
}

BlockMap::iterator mi = mapBlockIndex.find(blockHash);
if (mi != mapBlockIndex.end() && (*mi).second)
Expand Down
4 changes: 3 additions & 1 deletion src/masternode.h
Expand Up @@ -58,8 +58,9 @@ class CMasternodePing
READWRITE(vchSig);
}

bool CheckAndUpdate(int& nDos, bool fRequireEnabled = true);
bool CheckAndUpdate(int& nDos, bool fRequireEnabled = true, bool fCheckSigTimeOnly = false);
bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode);
bool VerifySignature(CPubKey& pubKeyMasternode, int &nDos);
void Relay();

uint256 GetHash(){
Expand Down Expand Up @@ -286,6 +287,7 @@ class CMasternodeBroadcast : public CMasternode
bool CheckAndUpdate(int& nDoS);
bool CheckInputsAndAdd(int& nDos);
bool Sign(CKey& keyCollateralAddress);
bool VerifySignature();
void Relay();

ADD_SERIALIZE_METHODS;
Expand Down

0 comments on commit 256e02f

Please sign in to comment.