Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V0.11.2.x masternodemanager #197

Merged
merged 13 commits into from
Feb 26, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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