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 = "";
if(!winner.IsValid(pfrom, strError)){
int nRank = 99999;
if(!winner.IsValid(pfrom, strError, nRank)){
if(strError != "") LogPrintf("mnw - invalid message - %s\n", strError);
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());
if(masternodePayments.AddWinningMasternode(winner)){
if(masternodePayments.AddWinningMasternode(winner, nRank)){
winner.Relay();
masternodeSync.AddedMasternodeWinner(winner.GetHash());
}
@ -471,7 +472,7 @@ bool CMasternodePayments::IsScheduled(CMasternode& mn, int nNotBlockHeight)
return false;
}
bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerIn)
bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerIn, int nRank)
{
uint256 blockHash = 0;
if(!GetBlockHash(blockHash, winnerIn.nBlockHeight-100)) {
@ -495,7 +496,7 @@ bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerI
int n = 1;
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;
}
@ -625,7 +626,7 @@ bool IsReferenceNode(CTxIn& vin)
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;
@ -646,15 +647,15 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError)
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
// 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);
Misbehaving(pnode->GetId(), 20);
}
@ -670,18 +671,19 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
//reference node - hybrid mode
int nRank = 9999;
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");
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;
}
}
@ -734,7 +736,7 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
{
LogPrintf("CMasternodePayments::ProcessBlock() - AddWinningMasternode\n");
if(AddWinningMasternode(newWinner))
if(AddWinningMasternode(newWinner, nRank))
{
newWinner.Relay();
nLastBlockHeight = nBlockHeight;
@ -779,19 +781,34 @@ void CMasternodePayments::Sync(CNode* node, int nCountNeeded)
if(chainActive.Tip() == NULL) return;
int nCount = (mnodeman.CountEnabled()*2);
int nCount = mnodeman.CountEnabled()*1.5;
if(nCountNeeded > nCount) nCountNeeded = nCount;
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();
while(it != mapMasternodePayeeVotes.end()) {
CMasternodePaymentWinner winner = (*it).second;
if(winner.nBlockHeight >= chainActive.Tip()->nHeight-nCountNeeded && winner.nBlockHeight <= chainActive.Tip()->nHeight + 20) {
CMasternodePaymentWinner& winner = (*it).second;
if(winner.nBlockHeight >= chainActive.Tip()->nHeight-5 && winner.nBlockHeight <= chainActive.Tip()->nHeight + 20) {
CInv inv(MSG_MASTERNODE_WINNER, winner.GetHash());
vInv.push_back(inv);
}
++it;
}
node->PushMessage("ssc", MASTERNODE_SYNC_MNW, (int)vInv.size());
if(vInv.size() > 0) node->PushMessage("inv", vInv);
}

View File

@ -63,15 +63,21 @@ class CMasternodePayee
public:
CScript scriptPubKey;
int nVotes;
uint256 nInvHash;
int nMasternodeRank;
CMasternodePayee() {
scriptPubKey = CScript();
nVotes = 0;
nInvHash = 0;
nMasternodeRank = 99999;
}
CMasternodePayee(CScript payee, int nVotesIn) {
CMasternodePayee(CScript payee, int nVotesIn, uint256 nInvHashIn, int nMasternodeRankIn) {
scriptPubKey = payee;
nVotes = nVotesIn;
nInvHash = nInvHashIn;
nMasternodeRank = nMasternodeRankIn;
}
ADD_SERIALIZE_METHODS;
@ -80,6 +86,8 @@ public:
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(scriptPubKey);
READWRITE(nVotes);
READWRITE(nInvHash);
READWRITE(nMasternodeRank);
}
};
@ -99,17 +107,23 @@ public:
vecPayments.clear();
}
void AddPayee(CScript payeeIn, int nIncrement){
void AddPayee(CScript payeeIn, int nIncrement, uint256 nInvHashIn, int nMasternodeRankIn){
LOCK(cs_vecPayments);
BOOST_FOREACH(CMasternodePayee& payee, vecPayments){
if(payee.scriptPubKey == payeeIn) {
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;
}
}
CMasternodePayee c(payeeIn, nIncrement);
CMasternodePayee c(payeeIn, nIncrement, nInvHashIn, nMasternodeRankIn);
vecPayments.push_back(c);
}
@ -128,6 +142,30 @@ public:
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)
{
LOCK(cs_vecPayments);
@ -183,7 +221,7 @@ public:
}
bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode);
bool IsValid(CNode* pnode, std::string& strError);
bool IsValid(CNode* pnode, std::string& strError, int& nRank);
bool SignatureValid();
void Relay();
@ -240,7 +278,7 @@ public:
mapMasternodePayeeVotes.clear();
}
bool AddWinningMasternode(CMasternodePaymentWinner& winner);
bool AddWinningMasternode(CMasternodePaymentWinner& winner, int nRank);
bool ProcessBlock(int nBlockHeight);
void Sync(CNode* node, int nCountNeeded);

View File

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

View File

@ -323,18 +323,7 @@ void CMasternodeMan::CheckAndRemove(bool forceExpiredRemoval)
++it2;
}
}
// 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
map<uint256, CMasternodePing>::iterator it4 = mapSeenMasternodePing.begin();
while(it4 != mapSeenMasternodePing.end()){

View File

@ -176,7 +176,7 @@ Value mnbudget(const Array& params, bool fHelp)
std::string strError = "";
int nConf = 0;
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()){