diff --git a/src/governance/governance.cpp b/src/governance/governance.cpp index d87fef40fac5..23a480b8d579 100644 --- a/src/governance/governance.cpp +++ b/src/governance/governance.cpp @@ -344,18 +344,25 @@ void CGovernanceManager::AddGovernanceObjectInternal(CGovernanceObject& insert_o LogPrint(BCLog::GOBJECT, "CGovernanceManager::AddGovernanceObject -- Before trigger block, GetDataAsPlainString = %s, nObjectType = %d\n", Assert(govobj)->GetDataAsPlainString(), std23::to_underlying(govobj->GetObjectType())); + // Count the attempt against the per-masternode rate buffer before any early + // return. Failed AddTrigger paths used to skip this, so a single operator + // key could flood mapObjects with unparseable triggers. + MasternodeRateUpdate(*govobj); + if (govobj->GetObjectType() == GovernanceObject::TRIGGER && !m_superblocks.AddTrigger(govobj, nCachedBlockHeight)) { LogPrint(BCLog::GOBJECT, "CGovernanceManager::AddGovernanceObject -- undo adding invalid trigger object: hash = %s\n", nHash.ToString()); govobj->PrepareDeletion(GetTime().count()); return; } + // Only objects we keep may be announced. Scheduling this before the AddTrigger + // check would make us re-announce, and serve on GETDATA, a trigger we just + // undid and marked for deletion. + ScheduleTriggerRelay(*govobj); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::AddGovernanceObject -- %s new, received from peer %s\n", strHash, peer_str); RelayObject(*govobj); - // Update the rate buffer - MasternodeRateUpdate(*govobj); - m_mn_sync.BumpAssetLastTime("CGovernanceManager::AddGovernanceObject"); // WE MIGHT HAVE PENDING/ORPHAN VOTES FOR THIS OBJECT @@ -701,15 +708,23 @@ void CGovernanceManager::MasternodeRateUpdate(const CGovernanceObject& govobj) it = mapLastMasternodeObject.insert(txout_m_t::value_type(masternodeOutpoint, last_object_rec(true))).first; } - int64_t nTimestamp = govobj.GetCreationTime(); - it->second.triggerBuffer.AddTimestamp(nTimestamp); + it->second.triggerBuffer.AddTimestamp(govobj.GetCreationTime()); + it->second.fStatusOK = true; +} + +void CGovernanceManager::ScheduleTriggerRelay(const CGovernanceObject& govobj) +{ + AssertLockHeld(cs_store); - if (nTimestamp > GetTime() + count_seconds(MAX_TIME_FUTURE_DEVIATION) - count_seconds(RELIABLE_PROPAGATION_TIME)) { - // schedule additional relay for the object + if (govobj.GetObjectType() != GovernanceObject::TRIGGER) return; + + // A trigger created this close to the future-deviation limit is still too new for + // peers with a lagging clock to accept, so re-announce it once it has aged past + // RELIABLE_PROPAGATION_TIME (see CheckPostponedObjects). + if (govobj.GetCreationTime() > + GetTime() + count_seconds(MAX_TIME_FUTURE_DEVIATION) - count_seconds(RELIABLE_PROPAGATION_TIME)) { setAdditionalRelayObjects.insert(govobj.GetHash()); } - - it->second.fStatusOK = true; } bool CGovernanceManager::MasternodeRateCheck(const CGovernanceObject& govobj, bool fUpdateFailStatus) diff --git a/src/governance/governance.h b/src/governance/governance.h index cca00d8cdb60..c062919e0c4f 100644 --- a/src/governance/governance.h +++ b/src/governance/governance.h @@ -403,6 +403,11 @@ class CGovernanceManager : public GovernanceStore void MasternodeRateUpdate(const CGovernanceObject& govobj) EXCLUSIVE_LOCKS_REQUIRED(cs_store); + /** Queue a deferred re-announcement for a trigger that is too new to propagate + * reliably yet. Only call this for triggers we are keeping. */ + void ScheduleTriggerRelay(const CGovernanceObject& govobj) + EXCLUSIVE_LOCKS_REQUIRED(cs_store); + bool MasternodeRateCheck(const CGovernanceObject& govobj, bool fUpdateFailStatus, bool fForce, bool& fRateCheckBypassed) EXCLUSIVE_LOCKS_REQUIRED(cs_store); diff --git a/src/test/governance_inv_tests.cpp b/src/test/governance_inv_tests.cpp index 93e63e9ac33f..c2e104572441 100644 --- a/src/test/governance_inv_tests.cpp +++ b/src/test/governance_inv_tests.cpp @@ -2,8 +2,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include +#include #include #include +#include #include #include #include @@ -13,52 +16,92 @@ #include #include #include +#include