Major masternode broadcast/ping changes (incompatible with prev version, proto bump required):
- Do not rely on local lastTimeSeen and requested fRequested anymore. Use last know (signed) ping instead and base all logic on that. Should reduce mn list difference between nodes. - Rework CActiveMasternode accordingly along with states, errorMessages, rpc etc. - Clean some related code, move parts from public to private - drop c_str in LogPrintf that were related to this functionality (todo: drop it for LogPrintf everywhere else)
This commit is contained in:
parent
bee6941195
commit
26fed43603
@ -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;
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -267,6 +267,9 @@ public:
|
||||
*/
|
||||
class CDarksendPool
|
||||
{
|
||||
private:
|
||||
mutable CCriticalSection cs_darksend;
|
||||
|
||||
public:
|
||||
enum messages {
|
||||
ERR_ALREADY_HAVE,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
173
src/masternode.h
173
src/masternode.h
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
|
@ -19,7 +19,6 @@
|
||||
#ifdef ENABLE_WALLET
|
||||
#include "wallet.h"
|
||||
#endif
|
||||
#include "masternodeman.h"
|
||||
#include "masternode-payments.h"
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user