Improve governance syncing efficiency with bloom filter (#1299)

* Use bloom filter for governance vote syncing

Modify masternode-sync to send bloom filters

Correctly initialize bloom filter

Set fUseFilter argument

Increase bloom filter size to account for multiple signals

Set bloom filter parameters

Use constants for bloom filter parameters

Added filter size check

Added filter size check in masternode-sync

Update bloom filter

Changed bloom parameters

* Bump protocol version

* Update sync time for inv's

* Changes based on code review comments

* Make bloom filter size network dependent

* Fix network dependent filter parameters

* Remove unneeded constant definition

* Move constant definition

* Add blank line
This commit is contained in:
Tim Flynn 2017-02-02 03:50:44 -05:00 committed by UdjinM6
parent cfc8954b42
commit 399330d42d
7 changed files with 69 additions and 11 deletions

View File

@ -84,6 +84,7 @@ public:
consensus.nSuperblockStartBlock = 600000; // TODO, the block at which 12.1 goes live.
consensus.nSuperblockCycle = 16616; // ~(60*24*30)/2.6, actual number of blocks per month is 200700 / 12 = 16725
consensus.nGovernanceMinQuorum = 10;
consensus.nGovernanceFilterElements = 20000;
consensus.nMasternodeMinimumConfirmations = 15;
consensus.nMajorityEnforceBlockUpgrade = 750;
consensus.nMajorityRejectBlockOutdated = 950;
@ -207,6 +208,7 @@ public:
consensus.nSuperblockStartBlock = 61000; // NOTE: Should satisfy nSuperblockStartBlock > nBudgetPeymentsStartBlock
consensus.nSuperblockCycle = 24; // Superblocks can be issued hourly on testnet
consensus.nGovernanceMinQuorum = 1;
consensus.nGovernanceFilterElements = 500;
consensus.nMasternodeMinimumConfirmations = 1;
consensus.nMajorityEnforceBlockUpgrade = 51;
consensus.nMajorityRejectBlockOutdated = 75;
@ -313,6 +315,7 @@ public:
consensus.nSuperblockStartBlock = 1500;
consensus.nSuperblockCycle = 10;
consensus.nGovernanceMinQuorum = 1;
consensus.nGovernanceFilterElements = 100;
consensus.nMasternodeMinimumConfirmations = 1;
consensus.nMajorityEnforceBlockUpgrade = 750;
consensus.nMajorityRejectBlockOutdated = 950;

View File

@ -48,6 +48,7 @@ struct Params {
int nSuperblockStartBlock;
int nSuperblockCycle; // in blocks
int nGovernanceMinQuorum; // Min absolute vote count to trigger an action
int nGovernanceFilterElements;
int nMasternodeMinimumConfirmations;
/** Used to check majorities for block version upgrade */
int nMajorityEnforceBlockUpgrade;

View File

@ -25,6 +25,9 @@ class CGovernanceVote;
static const int MAX_GOVERNANCE_OBJECT_DATA_SIZE = 16 * 1024;
static const int MIN_GOVERNANCE_PEER_PROTO_VERSION = 70204;
static const int GOVERNANCE_FILTER_PROTO_VERSION = 70206;
static const double GOVERNANCE_FILTER_FP_RATE = 0.001;
static const int GOVERNANCE_OBJECT_UNKNOWN = 0;
static const int GOVERNANCE_OBJECT_PROPOSAL = 1;

View File

@ -113,8 +113,18 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C
if (!masternodeSync.IsSynced()) return;
uint256 nProp;
CBloomFilter filter;
vRecv >> nProp;
if(pfrom->nVersion >= GOVERNANCE_FILTER_PROTO_VERSION) {
vRecv >> filter;
filter.UpdateEmptyFull();
}
else {
filter.clear();
}
if(nProp == uint256()) {
if(netfulfilledman.HasFulfilledRequest(pfrom->addr, NetMsgType::MNGOVERNANCESYNC)) {
// Asking for the whole list multiple times in a short period of time is no good
@ -125,7 +135,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C
netfulfilledman.AddFulfilledRequest(pfrom->addr, NetMsgType::MNGOVERNANCESYNC);
}
Sync(pfrom, nProp);
Sync(pfrom, nProp, filter);
LogPrint("gobject", "MNGOVERNANCESYNC -- syncing governance objects to our peer at %s\n", pfrom->addr.ToString());
}
@ -640,11 +650,14 @@ bool CGovernanceManager::ConfirmInventoryRequest(const CInv& inv)
LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest added inv to requested set\n");
}
// Keep sync alive
masternodeSync.AddedGovernanceItem();
LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest reached end, returning true\n");
return true;
}
void CGovernanceManager::Sync(CNode* pfrom, uint256 nProp)
void CGovernanceManager::Sync(CNode* pfrom, const uint256& nProp, const CBloomFilter& filter)
{
/*
@ -709,6 +722,9 @@ void CGovernanceManager::Sync(CNode* pfrom, uint256 nProp)
if(!vecVotes[i].IsValid(true)) {
continue;
}
if(filter.contains(vecVotes[i].GetHash())) {
continue;
}
pfrom->PushInventory(CInv(MSG_GOVERNANCE_OBJECT_VOTE, vecVotes[i].GetHash()));
++nVoteCount;
}
@ -927,13 +943,33 @@ void CGovernanceManager::CheckMasternodeOrphanObjects()
fRateChecksEnabled = true;
}
void CGovernanceManager::RequestGovernanceObject(CNode* pfrom, const uint256& nHash)
void CGovernanceManager::RequestGovernanceObject(CNode* pfrom, const uint256& nHash, bool fUseFilter)
{
if(!pfrom) {
return;
}
if(pfrom->nVersion < GOVERNANCE_FILTER_PROTO_VERSION) {
pfrom->PushMessage(NetMsgType::MNGOVERNANCESYNC, nHash);
return;
}
CBloomFilter filter;
filter.clear();
if(fUseFilter) {
CGovernanceObject* pObj = FindGovernanceObject(nHash);
if(pObj) {
filter = CBloomFilter(Params().GetConsensus().nGovernanceFilterElements, GOVERNANCE_FILTER_FP_RATE, GetRandInt(999999), BLOOM_UPDATE_ALL);
std::vector<CGovernanceVote> vecVotes = pObj->GetVoteFile().GetVotes();
for(size_t i = 0; i < vecVotes.size(); ++i) {
filter.insert(vecVotes[i].GetHash());
}
}
}
pfrom->PushMessage(NetMsgType::MNGOVERNANCESYNC, nHash, filter);
}
void CGovernanceManager::RequestGovernanceObjectVotes(CNode* pnode)
@ -979,7 +1015,7 @@ void CGovernanceManager::RequestGovernanceObjectVotes(const std::vector<CNode*>&
vpGovObjsTmp.erase(vpGovObjsTmp.begin() + r);
}
LogPrintf("CGovernanceManager::RequestGovernanceObjectVotes -- Requesting votes for %s, peer=%d\n", nHashGovobj.ToString(), pnode->id);
RequestGovernanceObject(pnode, nHashGovobj);
RequestGovernanceObject(pnode, nHashGovobj, true);
mapAskedRecently[nHashGovobj] = nNow + mapObjects.size() * 60; // ask again after full cycle
}
}

View File

@ -7,6 +7,7 @@
//#define ENABLE_DASH_DEBUG
#include "bloom.h"
#include "cachemap.h"
#include "cachemultimap.h"
#include "chain.h"
@ -271,7 +272,7 @@ public:
*/
bool ConfirmInventoryRequest(const CInv& inv);
void Sync(CNode* node, uint256 nProp);
void Sync(CNode* node, const uint256& nProp, const CBloomFilter& filter);
void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
@ -379,7 +380,7 @@ public:
void RequestGovernanceObjectVotes(const std::vector<CNode*>& vNodesCopy);
private:
void RequestGovernanceObject(CNode* pfrom, const uint256& nHash);
void RequestGovernanceObject(CNode* pfrom, const uint256& nHash, bool fUseFilter = false);
void AddInvalidVote(const CGovernanceVote& vote)
{

View File

@ -344,8 +344,7 @@ void CMasternodeSync::ProcessTick()
} else if(nRequestedMasternodeAttempt < 6) {
int nMnCount = mnodeman.CountMasternodes();
pnode->PushMessage(NetMsgType::MASTERNODEPAYMENTSYNC, nMnCount); //sync payment votes
uint256 n = uint256();
pnode->PushMessage(NetMsgType::MNGOVERNANCESYNC, n); //sync masternode votes
SendGovernanceSyncRequest(pnode);
} else {
nRequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED;
}
@ -497,7 +496,7 @@ void CMasternodeSync::ProcessTick()
if (pnode->nVersion < MIN_GOVERNANCE_PEER_PROTO_VERSION) continue;
nRequestedMasternodeAttempt++;
pnode->PushMessage(NetMsgType::MNGOVERNANCESYNC, uint256()); //sync masternode votes
SendGovernanceSyncRequest(pnode);
ReleaseNodes(vNodesCopy);
return; //this will cause each peer to get one request each six seconds for the various assets we need
@ -508,6 +507,19 @@ void CMasternodeSync::ProcessTick()
ReleaseNodes(vNodesCopy);
}
void CMasternodeSync::SendGovernanceSyncRequest(CNode* pnode)
{
if(pnode->nVersion >= GOVERNANCE_FILTER_PROTO_VERSION) {
CBloomFilter filter;
filter.clear();
pnode->PushMessage(NetMsgType::MNGOVERNANCESYNC, uint256(), filter);
}
else {
pnode->PushMessage(NetMsgType::MNGOVERNANCESYNC, uint256());
}
}
void CMasternodeSync::UpdatedBlockTip(const CBlockIndex *pindex)
{
pCurrentBlockIndex = pindex;

View File

@ -67,6 +67,8 @@ public:
void AddedPaymentVote() { nTimeLastPaymentVote = GetTime(); }
void AddedGovernanceItem() { nTimeLastGovernanceItem = GetTime(); };
void SendGovernanceSyncRequest(CNode* pnode);
bool IsFailed() { return nRequestedMasternodeAssets == MASTERNODE_SYNC_FAILED; }
bool IsBlockchainSynced(bool fBlockAccepted = false);
bool IsMasternodeListSynced() { return nRequestedMasternodeAssets > MASTERNODE_SYNC_LIST; }