Skip to content

Commit

Permalink
Merge pull request #197 from UdjinM6/v0.11.2.x_masternodemanager
Browse files Browse the repository at this point in the history
V0.11.2.x masternodemanager
  • Loading branch information
evan82 committed Feb 26, 2015
2 parents d8307c5 + 2e05bf2 commit 97d88a6
Show file tree
Hide file tree
Showing 21 changed files with 1,214 additions and 728 deletions.
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ BITCOIN_CORE_H = \
limitedmap.h \
main.h \
masternode.h \
masternodeman.h \
masternodeconfig.h \
miner.h \
mruset.h \
Expand Down Expand Up @@ -151,6 +152,7 @@ libdarkcoin_common_a_SOURCES = \
core.cpp \
darksend.cpp \
masternode.cpp \
masternodeman.cpp \
masternodeconfig.cpp \
instantx.cpp \
hash.cpp \
Expand Down
55 changes: 12 additions & 43 deletions src/activemasternode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "core.h"
#include "protocol.h"
#include "activemasternode.h"
#include "masternodeman.h"
#include <boost/lexical_cast.hpp>

//
Expand Down Expand Up @@ -200,16 +201,13 @@ bool CActiveMasternode::Dseep(CTxIn vin, CService service, CKey keyMasternode, C
}

// Update Last Seen timestamp in masternode list
bool found = false;
BOOST_FOREACH(CMasterNode& mn, vecMasternodes) {
//LogPrintf(" -- %s\n", mn.vin.ToString().c_str());
if(mn.vin == vin) {
found = true;
mn.UpdateLastSeen();
}
CMasternode* pmn = mnodeman.Find(vin);
if(pmn != NULL)
{
pmn->UpdateLastSeen();
}

if(!found){
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::Dseep() - Error: %s\n", retErrorMessage.c_str());
Expand Down Expand Up @@ -269,16 +267,13 @@ bool CActiveMasternode::Register(CTxIn vin, CService service, CKey keyCollateral
return false;
}

bool found = false;
BOOST_FOREACH(CMasterNode& mn, vecMasternodes)
if(mn.vin == vin)
found = true;

if(!found) {
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());
CMasterNode mn(service, vin, pubKeyCollateralAddress, vchMasterNodeSignature, masterNodeSignatureTime, pubKeyMasternode, PROTOCOL_VERSION);
CMasternode mn(service, vin, pubKeyCollateralAddress, vchMasterNodeSignature, masterNodeSignatureTime, pubKeyMasternode, PROTOCOL_VERSION);
mn.UpdateLastSeen(masterNodeSignatureTime);
vecMasternodes.push_back(mn);
mnodeman.Add(mn);
}

//send to all peers
Expand Down Expand Up @@ -378,32 +373,6 @@ vector<COutput> CActiveMasternode::SelectCoinsMasternode()
return filteredCoins;
}


/* select coins with specified transaction hash and output index */
/*
bool CActiveMasternode::SelectCoinsMasternode(CTxIn& vin, int64& nValueIn, CScript& pubScript, std::string strTxHash, std::string strOutputIndex)
{
CWalletTx ctx;
// Convert configuration strings
uint256 txHash;
int outputIndex;
txHash.SetHex(strTxHash);
std::istringstream(strOutputIndex) >> outputIndex;
if(pwalletMain->GetTransaction(txHash, ctx)) {
if(ctx.vout[outputIndex].nValue == 1000*COIN) { //exactly
vin = CTxIn(ctx.GetHash(), outputIndex);
pubScript = ctx.vout[outputIndex].scriptPubKey; // the inputs PubKey
nValueIn = ctx.vout[outputIndex].nValue;
return true;
}
}
return false;
}
*/

// when starting a masternode, this can enable to run as a hot wallet with no funds
bool CActiveMasternode::EnableHotColdMasterNode(CTxIn& newVin, CService& newService)
{
Expand Down
2 changes: 0 additions & 2 deletions src/activemasternode.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ class CActiveMasternode
vector<COutput> SelectCoinsMasternode();
bool GetVinFromOutput(COutput out, CTxIn& vin, CPubKey& pubkey, CKey& secretKey);

//bool SelectCoinsMasternode(CTxIn& vin, int64& nValueIn, CScript& pubScript, std::string strTxHash, std::string strOutputIndex);

// enable hot wallet mode (run a masternode with no funds)
bool EnableHotColdMasterNode(CTxIn& vin, CService& addr);
};
Expand Down
128 changes: 65 additions & 63 deletions src/darksend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include "main.h"
#include "init.h"
#include "util.h"
#include "masternode.h"
#include "masternodeman.h"
#include "instantx.h"
#include "ui_interface.h"

Expand Down Expand Up @@ -121,17 +121,18 @@ void ProcessMessageDarksend(CNode* pfrom, std::string& strCommand, CDataStream&
vRecv >> nDenom >> txCollateral;

std::string error = "";
int mn = GetMasternodeByVin(activeMasternode.vin);
if(mn == -1){
CMasternode* pmn = mnodeman.Find(activeMasternode.vin);
if(pmn == NULL)
{
std::string strError = _("Not in the masternode list.");
pfrom->PushMessage("dssu", darkSendPool.sessionID, darkSendPool.GetState(), darkSendPool.GetEntriesCount(), MASTERNODE_REJECTED, strError);
return;
}

if(darkSendPool.sessionUsers == 0) {
if(vecMasternodes[mn].nLastDsq != 0 &&
vecMasternodes[mn].nLastDsq + CountMasternodesAboveProtocol(darkSendPool.MIN_PEER_PROTO_VERSION)/5 > darkSendPool.nDsqCount){
//LogPrintf("dsa -- last dsq too recent, must wait. %s \n", vecMasternodes[mn].addr.ToString().c_str());
if(pmn->nLastDsq != 0 &&
pmn->nLastDsq + mnodeman.CountMasternodesAboveProtocol(darkSendPool.MIN_PEER_PROTO_VERSION)/5 > darkSendPool.nDsqCount){
LogPrintf("dsa -- last dsq too recent, must wait. %s \n", pmn->addr.ToString().c_str());
std::string strError = _("Last Darksend was too recent.");
pfrom->PushMessage("dssu", darkSendPool.sessionID, darkSendPool.GetState(), darkSendPool.GetEntriesCount(), MASTERNODE_REJECTED, strError);
return;
Expand Down Expand Up @@ -164,8 +165,8 @@ void ProcessMessageDarksend(CNode* pfrom, std::string& strCommand, CDataStream&

if(dsq.IsExpired()) return;

int mn = GetMasternodeByVin(dsq.vin);
if(mn == -1) return;
CMasternode* pmn = mnodeman.Find(dsq.vin);
if(pmn == NULL) return;

// if the queue is ready, submit if we can
if(dsq.ready) {
Expand All @@ -181,16 +182,16 @@ void ProcessMessageDarksend(CNode* pfrom, std::string& strCommand, CDataStream&
if(q.vin == dsq.vin) return;
}

if(fDebug) LogPrintf("dsq last %d last2 %d count %d\n", vecMasternodes[mn].nLastDsq, vecMasternodes[mn].nLastDsq + (int)vecMasternodes.size()/5, darkSendPool.nDsqCount);
if(fDebug) LogPrintf("dsq last %d last2 %d count %d\n", pmn->nLastDsq, pmn->nLastDsq + mnodeman.size()/5, darkSendPool.nDsqCount);
//don't allow a few nodes to dominate the queuing process
if(vecMasternodes[mn].nLastDsq != 0 &&
vecMasternodes[mn].nLastDsq + CountMasternodesAboveProtocol(darkSendPool.MIN_PEER_PROTO_VERSION)/5 > darkSendPool.nDsqCount){
if(fDebug) LogPrintf("dsq -- masternode sending too many dsq messages. %s \n", vecMasternodes[mn].addr.ToString().c_str());
if(pmn->nLastDsq != 0 &&
pmn->nLastDsq + mnodeman.CountMasternodesAboveProtocol(darkSendPool.MIN_PEER_PROTO_VERSION)/5 > darkSendPool.nDsqCount){
if(fDebug) LogPrintf("dsq -- masternode sending too many dsq messages. %s \n", pmn->addr.ToString().c_str());
return;
}
darkSendPool.nDsqCount++;
vecMasternodes[mn].nLastDsq = darkSendPool.nDsqCount;
vecMasternodes[mn].allowFreeTx = true;
pmn->nLastDsq = darkSendPool.nDsqCount;
pmn->allowFreeTx = true;

if(fDebug) LogPrintf("dsq - new darksend queue object - %s\n", addr.ToString().c_str());
vecDarksendQueue.push_back(dsq);
Expand Down Expand Up @@ -484,6 +485,23 @@ int GetInputDarksendRounds(CTxIn in, int rounds)
return rounds-1;
}

// manage the masternode connections
void CDarkSendPool::ProcessMasternodeConnections()
{
LOCK(cs_vNodes);

BOOST_FOREACH(CNode* pnode, vNodes)
{
//if it's our masternode, let it be
if(submittedToMasternode == pnode->addr) continue;

if(pnode->fDarkSendMaster){
LogPrintf("Closing masternode connection %s \n", pnode->addr.ToString().c_str());
pnode->CloseSocketDisconnect();
}
}
}

void CDarkSendPool::Reset(){
cachedLastSuccess = 0;
vecMasternodesUsed.clear();
Expand Down Expand Up @@ -1357,7 +1375,6 @@ void CDarkSendPool::NewBlock()
if(!fMasterNode){
//denominate all non-denominated inputs every 25 minutes.
if(chainActive.Tip()->nHeight % 10 == 0) UnlockCoins();
ProcessMasternodeConnections();
}
}

Expand Down Expand Up @@ -1426,7 +1443,7 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready)
}
}

if(vecMasternodes.size() == 0){
if(mnodeman.size() == 0){
if(fDebug) LogPrintf("CDarkSendPool::DoAutomaticDenominating - No masternodes detected\n");
strAutoDenomResult = _("No masternodes detected.");
return false;
Expand Down Expand Up @@ -1579,40 +1596,39 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready)
}
}

//shuffle masternodes around before we try to connect
std::random_shuffle ( vecMasternodes.begin(), vecMasternodes.end() );
int i = 0;

// otherwise, try one randomly
while(i < 10)
{
CMasternode* mn = mnodeman.FindRandom();
//don't reuse masternodes
BOOST_FOREACH(CTxIn usedVin, vecMasternodesUsed) {
if(vecMasternodes[i].vin == usedVin){
if(mn->vin == usedVin){
i++;
continue;
}
}
if(vecMasternodes[i].protocolVersion < MIN_PEER_PROTO_VERSION) {
if(mn->protocolVersion < darkSendPool.MIN_PEER_PROTO_VERSION) {
i++;
continue;
}

if(vecMasternodes[i].nLastDsq != 0 &&
vecMasternodes[i].nLastDsq + CountMasternodesAboveProtocol(darkSendPool.MIN_PEER_PROTO_VERSION)/5 > darkSendPool.nDsqCount){
if(mn->nLastDsq != 0 &&
mn->nLastDsq + mnodeman.CountMasternodesAboveProtocol(darkSendPool.MIN_PEER_PROTO_VERSION)/5 > darkSendPool.nDsqCount){
i++;
continue;
}

lastTimeChanged = GetTimeMillis();
LogPrintf("DoAutomaticDenominating -- attempt %d connection to masternode %s\n", i, vecMasternodes[i].addr.ToString().c_str());
if(ConnectNode((CAddress)vecMasternodes[i].addr, NULL, true)){
submittedToMasternode = vecMasternodes[i].addr;
submittedToMasternode = mn->addr;
LogPrintf("DoAutomaticDenominating -- attempt %d connection to masternode %s\n", i, mn->addr.ToString().c_str());
if(ConnectNode((CAddress)mn->addr, NULL, true)){

LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
if((CNetAddr)pnode->addr != (CNetAddr)vecMasternodes[i].addr) continue;
if((CNetAddr)pnode->addr != (CNetAddr)mn->addr) continue;

std::string strReason;
if(txCollateral == CTransaction()){
Expand All @@ -1622,7 +1638,7 @@ bool CDarkSendPool::DoAutomaticDenominating(bool fDryRun, bool ready)
}
}

vecMasternodesUsed.push_back(vecMasternodes[i].vin);
vecMasternodesUsed.push_back(mn->vin);

std::vector<int64_t> vecAmounts;
pwalletMain->ConvertList(vCoins, vecAmounts);
Expand Down Expand Up @@ -2115,18 +2131,18 @@ bool CDarksendQueue::Relay()

bool CDarksendQueue::CheckSignature()
{
BOOST_FOREACH(CMasterNode& mn, vecMasternodes) {
CMasternode* pmn = mnodeman.Find(vin);

if(mn.vin == vin) {
std::string strMessage = vin.ToString() + boost::lexical_cast<std::string>(nDenom) + boost::lexical_cast<std::string>(time) + boost::lexical_cast<std::string>(ready);

std::string errorMessage = "";
if(!darkSendSigner.VerifyMessage(mn.pubkey2, vchSig, strMessage, errorMessage)){
return error("CDarksendQueue::CheckSignature() - Got bad masternode address signature %s \n", vin.ToString().c_str());
}
if(pmn != NULL)
{
std::string strMessage = vin.ToString() + boost::lexical_cast<std::string>(nDenom) + boost::lexical_cast<std::string>(time) + boost::lexical_cast<std::string>(ready);

return true;
std::string errorMessage = "";
if(!darkSendSigner.VerifyMessage(pmn->pubkey2, vchSig, strMessage, errorMessage)){
return error("CDarksendQueue::CheckSignature() - Got bad masternode address signature %s \n", vin.ToString().c_str());
}

return true;
}

return false;
Expand All @@ -2152,36 +2168,24 @@ void ThreadCheckDarkSendPool()
//LogPrintf("ThreadCheckDarkSendPool::check timeout\n");
darkSendPool.CheckTimeout();

if(c % 60 == 0){
if(c % 60 == 0)
{
LOCK(cs_main);
/*
cs_main is required for doing masternode.Check because something
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.
*/

vector<CMasterNode>::iterator it = vecMasternodes.begin();
//check them separately
while(it != vecMasternodes.end()){
(*it).Check();
++it;
}

//remove inactive
it = vecMasternodes.begin();
while(it != vecMasternodes.end()){
if((*it).enabled == 4 || (*it).enabled == 3){
LogPrintf("Removing inactive masternode %s\n", (*it).addr.ToString().c_str());
it = vecMasternodes.erase(it);
} else {
++it;
}
}

mnodeman.CheckAndRemove();
darkSendPool.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 && RequestedMasterNodeList < 3){
bool fIsInitialDownload = IsInitialBlockDownload();
Expand All @@ -2197,7 +2201,9 @@ void ThreadCheckDarkSendPool()

LogPrintf("Successfully synced, asking for Masternode list and payment list\n");

pnode->PushMessage("dseg", CTxIn()); //request full mn list
//request full mn list only if masternodes.dat was updated quite a long time ago
mnodeman.DsegUpdate(pnode);

pnode->PushMessage("mnget"); //sync payees
pnode->PushMessage("getsporks"); //get current network sporks
RequestedMasterNodeList++;
Expand All @@ -2206,13 +2212,9 @@ void ThreadCheckDarkSendPool()
}
}

if(c % MASTERNODE_PING_SECONDS == 0){
activeMasternode.ManageStatus();
}

if(c % 60 == 0){
//if we've used 1/5 of the masternode list, then clear the list.
if((int)vecMasternodesUsed.size() > (int)vecMasternodes.size() / 5)
if((int)vecMasternodesUsed.size() > (int)mnodeman.size() / 5)
vecMasternodesUsed.clear();
}

Expand Down
Loading

0 comments on commit 97d88a6

Please sign in to comment.