Drastically reduce bandwidth/cpu usage for syncing

- Only send 1 winner per block for the previous 4500 blocks (was 10 items per block for 6000 blocks)
- Send full sync for last 5 blocks and next 20 blocks
- Turn off mnb cleaning, there aren't that many broadcasts on the network and this could cause problems in some cases
- Fix budget submission collateral check
This commit is contained in:
Evan Duffield 2015-08-28 14:37:53 -07:00
parent 22745a81eb
commit 2ee9abd060
6 changed files with 85 additions and 38 deletions

View File

@ -382,7 +382,8 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
} }
std::string strError = ""; std::string strError = "";
if(!winner.IsValid(pfrom, strError)){ int nRank = 99999;
if(!winner.IsValid(pfrom, strError, nRank)){
if(strError != "") LogPrintf("mnw - invalid message - %s\n", strError); if(strError != "") LogPrintf("mnw - invalid message - %s\n", strError);
return; return;
} }
@ -406,7 +407,7 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
LogPrint("mnpayments", "mnw - winning vote - Addr %s Height %d bestHeight %d - %s\n", address2.ToString().c_str(), winner.nBlockHeight, chainActive.Tip()->nHeight, winner.vinMasternode.prevout.ToStringShort()); LogPrint("mnpayments", "mnw - winning vote - Addr %s Height %d bestHeight %d - %s\n", address2.ToString().c_str(), winner.nBlockHeight, chainActive.Tip()->nHeight, winner.vinMasternode.prevout.ToStringShort());
if(masternodePayments.AddWinningMasternode(winner)){ if(masternodePayments.AddWinningMasternode(winner, nRank)){
winner.Relay(); winner.Relay();
masternodeSync.AddedMasternodeWinner(winner.GetHash()); masternodeSync.AddedMasternodeWinner(winner.GetHash());
} }
@ -471,7 +472,7 @@ bool CMasternodePayments::IsScheduled(CMasternode& mn, int nNotBlockHeight)
return false; return false;
} }
bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerIn) bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerIn, int nRank)
{ {
uint256 blockHash = 0; uint256 blockHash = 0;
if(!GetBlockHash(blockHash, winnerIn.nBlockHeight-100)) { if(!GetBlockHash(blockHash, winnerIn.nBlockHeight-100)) {
@ -495,7 +496,7 @@ bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerI
int n = 1; int n = 1;
if(IsReferenceNode(winnerIn.vinMasternode)) n = 100; if(IsReferenceNode(winnerIn.vinMasternode)) n = 100;
mapMasternodeBlocks[winnerIn.nBlockHeight].AddPayee(winnerIn.payee, n); mapMasternodeBlocks[winnerIn.nBlockHeight].AddPayee(winnerIn.payee, n, winnerIn.GetHash(), nRank);
return true; return true;
} }
@ -625,7 +626,7 @@ bool IsReferenceNode(CTxIn& vin)
return false; return false;
} }
bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError) bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError, int& nRank)
{ {
if(IsReferenceNode(vinMasternode)) return true; if(IsReferenceNode(vinMasternode)) return true;
@ -646,15 +647,15 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError)
return false; return false;
} }
int n = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight-100, MIN_MNW_PEER_PROTO_VERSION); nRank = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight-100, MIN_MNW_PEER_PROTO_VERSION);
if(n > MNPAYMENTS_SIGNATURES_TOTAL) if(nRank > MNPAYMENTS_SIGNATURES_TOTAL)
{ {
//It's common to have masternodes mistakenly think they are in the top 10 //It's common to have masternodes mistakenly think they are in the top 10
// We don't want to print all of these messages, or punish them unless they're way off // We don't want to print all of these messages, or punish them unless they're way off
if(n > MNPAYMENTS_SIGNATURES_TOTAL*2) if(nRank > MNPAYMENTS_SIGNATURES_TOTAL*2)
{ {
strError = strprintf("Masternode not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL, n); strError = strprintf("Masternode not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL, nRank);
LogPrintf("CMasternodePaymentWinner::IsValid - %s\n", strError); LogPrintf("CMasternodePaymentWinner::IsValid - %s\n", strError);
Misbehaving(pnode->GetId(), 20); Misbehaving(pnode->GetId(), 20);
} }
@ -670,18 +671,19 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
//reference node - hybrid mode //reference node - hybrid mode
int nRank = 9999;
if(!IsReferenceNode(activeMasternode.vin)){ if(!IsReferenceNode(activeMasternode.vin)){
int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight-100, MIN_MNW_PEER_PROTO_VERSION); int nRank = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight-100, MIN_MNW_PEER_PROTO_VERSION);
if(n == -1) if(nRank == -1)
{ {
LogPrint("mnpayments", "CMasternodePayments::ProcessBlock - Unknown Masternode\n"); LogPrint("mnpayments", "CMasternodePayments::ProcessBlock - Unknown Masternode\n");
return false; return false;
} }
if(n > MNPAYMENTS_SIGNATURES_TOTAL) if(nRank > MNPAYMENTS_SIGNATURES_TOTAL)
{ {
LogPrint("mnpayments", "CMasternodePayments::ProcessBlock - Masternode not in the top %d (%d)\n", MNPAYMENTS_SIGNATURES_TOTAL, n); LogPrint("mnpayments", "CMasternodePayments::ProcessBlock - Masternode not in the top %d (%d)\n", MNPAYMENTS_SIGNATURES_TOTAL, nRank);
return false; return false;
} }
} }
@ -734,7 +736,7 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
{ {
LogPrintf("CMasternodePayments::ProcessBlock() - AddWinningMasternode\n"); LogPrintf("CMasternodePayments::ProcessBlock() - AddWinningMasternode\n");
if(AddWinningMasternode(newWinner)) if(AddWinningMasternode(newWinner, nRank))
{ {
newWinner.Relay(); newWinner.Relay();
nLastBlockHeight = nBlockHeight; nLastBlockHeight = nBlockHeight;
@ -779,19 +781,34 @@ void CMasternodePayments::Sync(CNode* node, int nCountNeeded)
if(chainActive.Tip() == NULL) return; if(chainActive.Tip() == NULL) return;
int nCount = (mnodeman.CountEnabled()*2); int nCount = mnodeman.CountEnabled()*1.5;
if(nCountNeeded > nCount) nCountNeeded = nCount; if(nCountNeeded > nCount) nCountNeeded = nCount;
vector<CInv> vInv; vector<CInv> vInv;
//get 1 winner per block for the previous nCount blocks
vector<uint256> vecHash;
for(int nBlockHeight = chainActive.Tip()->nHeight-nCount; nBlockHeight < chainActive.Tip()->nHeight-5; nBlockHeight++)
{
if(mapMasternodeBlocks[nBlockHeight].GetPayeeInventoryItems(vecHash)){
BOOST_FOREACH(uint256& nHash, vecHash)
{
CInv inv(MSG_MASTERNODE_WINNER, nHash);
vInv.push_back(inv);
}
}
}
//get 10 winners per block for the previous 5 blocks and next 20 (usually will be 10 though)
std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin(); std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin();
while(it != mapMasternodePayeeVotes.end()) { while(it != mapMasternodePayeeVotes.end()) {
CMasternodePaymentWinner winner = (*it).second; CMasternodePaymentWinner& winner = (*it).second;
if(winner.nBlockHeight >= chainActive.Tip()->nHeight-nCountNeeded && winner.nBlockHeight <= chainActive.Tip()->nHeight + 20) { if(winner.nBlockHeight >= chainActive.Tip()->nHeight-5 && winner.nBlockHeight <= chainActive.Tip()->nHeight + 20) {
CInv inv(MSG_MASTERNODE_WINNER, winner.GetHash()); CInv inv(MSG_MASTERNODE_WINNER, winner.GetHash());
vInv.push_back(inv); vInv.push_back(inv);
} }
++it; ++it;
} }
node->PushMessage("ssc", MASTERNODE_SYNC_MNW, (int)vInv.size()); node->PushMessage("ssc", MASTERNODE_SYNC_MNW, (int)vInv.size());
if(vInv.size() > 0) node->PushMessage("inv", vInv); if(vInv.size() > 0) node->PushMessage("inv", vInv);
} }

View File

@ -63,15 +63,21 @@ class CMasternodePayee
public: public:
CScript scriptPubKey; CScript scriptPubKey;
int nVotes; int nVotes;
uint256 nInvHash;
int nMasternodeRank;
CMasternodePayee() { CMasternodePayee() {
scriptPubKey = CScript(); scriptPubKey = CScript();
nVotes = 0; nVotes = 0;
nInvHash = 0;
nMasternodeRank = 99999;
} }
CMasternodePayee(CScript payee, int nVotesIn) { CMasternodePayee(CScript payee, int nVotesIn, uint256 nInvHashIn, int nMasternodeRankIn) {
scriptPubKey = payee; scriptPubKey = payee;
nVotes = nVotesIn; nVotes = nVotesIn;
nInvHash = nInvHashIn;
nMasternodeRank = nMasternodeRankIn;
} }
ADD_SERIALIZE_METHODS; ADD_SERIALIZE_METHODS;
@ -80,6 +86,8 @@ public:
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(scriptPubKey); READWRITE(scriptPubKey);
READWRITE(nVotes); READWRITE(nVotes);
READWRITE(nInvHash);
READWRITE(nMasternodeRank);
} }
}; };
@ -99,17 +107,23 @@ public:
vecPayments.clear(); vecPayments.clear();
} }
void AddPayee(CScript payeeIn, int nIncrement){ void AddPayee(CScript payeeIn, int nIncrement, uint256 nInvHashIn, int nMasternodeRankIn){
LOCK(cs_vecPayments); LOCK(cs_vecPayments);
BOOST_FOREACH(CMasternodePayee& payee, vecPayments){ BOOST_FOREACH(CMasternodePayee& payee, vecPayments){
if(payee.scriptPubKey == payeeIn) { if(payee.scriptPubKey == payeeIn) {
payee.nVotes += nIncrement; payee.nVotes += nIncrement;
//keep track of the "best" (highest rank) masternode's inventory item so we can send that one
// when syncing, we will consume much less bandwidth because of this
if(payee.nMasternodeRank > nMasternodeRankIn){
payee.nMasternodeRank = nMasternodeRankIn;
payee.nInvHash = nInvHashIn;
}
return; return;
} }
} }
CMasternodePayee c(payeeIn, nIncrement); CMasternodePayee c(payeeIn, nIncrement, nInvHashIn, nMasternodeRankIn);
vecPayments.push_back(c); vecPayments.push_back(c);
} }
@ -128,6 +142,30 @@ public:
return (nVotes > -1); return (nVotes > -1);
} }
int CountVotes()
{
int nVotes = 0;
BOOST_FOREACH(CMasternodePayee& p, vecPayments)
nVotes += p.nVotes;
return nVotes;
}
bool GetPayeeInventoryItems(vector<uint256>& vecHash)
{
LOCK(cs_vecPayments);
BOOST_FOREACH(CMasternodePayee& p, vecPayments){
//if we're syncing another client from a partial list, send everything.
// otherwise, we'll require 2 votes per item (those are the ones that count on the winners list)
if(p.nVotes >= 2 || CountVotes() <= 5){
vecHash.push_back(p.nInvHash);
}
}
return vecHash.size() >= 1;
}
bool HasPayeeWithVotes(CScript payee, int nVotesReq) bool HasPayeeWithVotes(CScript payee, int nVotesReq)
{ {
LOCK(cs_vecPayments); LOCK(cs_vecPayments);
@ -183,7 +221,7 @@ public:
} }
bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode); bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode);
bool IsValid(CNode* pnode, std::string& strError); bool IsValid(CNode* pnode, std::string& strError, int& nRank);
bool SignatureValid(); bool SignatureValid();
void Relay(); void Relay();
@ -240,7 +278,7 @@ public:
mapMasternodePayeeVotes.clear(); mapMasternodePayeeVotes.clear();
} }
bool AddWinningMasternode(CMasternodePaymentWinner& winner); bool AddWinningMasternode(CMasternodePaymentWinner& winner, int nRank);
bool ProcessBlock(int nBlockHeight); bool ProcessBlock(int nBlockHeight);
void Sync(CNode* node, int nCountNeeded); void Sync(CNode* node, int nCountNeeded);

View File

@ -348,7 +348,7 @@ void CMasternodeSync::Process()
CBlockIndex* pindexPrev = chainActive.Tip(); CBlockIndex* pindexPrev = chainActive.Tip();
if(pindexPrev == NULL) return; if(pindexPrev == NULL) return;
int nMnCount = mnodeman.CountEnabled()*2; int nMnCount = mnodeman.CountEnabled();
pnode->PushMessage("mnget", nMnCount); //sync payees pnode->PushMessage("mnget", nMnCount); //sync payees
RequestedMasternodeAttempt++; RequestedMasternodeAttempt++;

View File

@ -271,7 +271,10 @@ int64_t CMasternode::GetLastPaid() {
Search for this payee, with at least 2 votes. This will aid in consensus allowing the network Search for this payee, with at least 2 votes. This will aid in consensus allowing the network
to converge on the same payees quickly, then keep the same schedule. to converge on the same payees quickly, then keep the same schedule.
*/ */
if(masternodePayments.mapMasternodeBlocks[BlockReading->nHeight].HasPayeeWithVotes(mnpayee, 2)){
//if we've synced we'll have 1 vote per winning masternode, those count. Otherwise we'll have 10 votes, then only 2 votes min count
int nMinVotes = masternodePayments.mapMasternodeBlocks[BlockReading->nHeight].CountVotes() >= 6 ? 2 : 1;
if(masternodePayments.mapMasternodeBlocks[BlockReading->nHeight].HasPayeeWithVotes(mnpayee, nMinVotes)){
return BlockReading->nTime + nOffset; return BlockReading->nTime + nOffset;
} }
} }

View File

@ -324,17 +324,6 @@ void CMasternodeMan::CheckAndRemove(bool forceExpiredRemoval)
} }
} }
// remove expired mapSeenMasternodeBroadcast
map<uint256, CMasternodeBroadcast>::iterator it3 = mapSeenMasternodeBroadcast.begin();
while(it3 != mapSeenMasternodeBroadcast.end()){
if((*it3).second.lastPing.sigTime < GetTime()-(MASTERNODE_REMOVAL_SECONDS*2)){
mapSeenMasternodeBroadcast.erase(it3++);
masternodeSync.mapSeenSyncMNB.erase((*it3).second.GetHash());
} else {
++it3;
}
}
// remove expired mapSeenMasternodePing // remove expired mapSeenMasternodePing
map<uint256, CMasternodePing>::iterator it4 = mapSeenMasternodePing.begin(); map<uint256, CMasternodePing>::iterator it4 = mapSeenMasternodePing.begin();
while(it4 != mapSeenMasternodePing.end()){ while(it4 != mapSeenMasternodePing.end()){

View File

@ -176,7 +176,7 @@ Value mnbudget(const Array& params, bool fHelp)
std::string strError = ""; std::string strError = "";
int nConf = 0; int nConf = 0;
if(!IsBudgetCollateralValid(hash, budgetProposalBroadcast.GetHash(), strError, budgetProposalBroadcast.nTime, nConf)){ if(!IsBudgetCollateralValid(hash, budgetProposalBroadcast.GetHash(), strError, budgetProposalBroadcast.nTime, nConf)){
//return "Proposal FeeTX is not valid - " + hash.ToString() + " - " + strError; return "Proposal FeeTX is not valid - " + hash.ToString() + " - " + strError;
} }
if(!masternodeSync.IsBlockchainSynced()){ if(!masternodeSync.IsBlockchainSynced()){