Skip to content

Commit 784ba27

Browse files
committed
more 16426: governance
1 parent 343e2b6 commit 784ba27

File tree

6 files changed

+52
-62
lines changed

6 files changed

+52
-62
lines changed

src/governance/governance.cpp

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ CGovernanceManager::CGovernanceManager() :
4848
// Accessors for thread-safe access to maps
4949
bool CGovernanceManager::HaveObjectForHash(const uint256& nHash) const
5050
{
51-
LOCK(cs);
51+
LOCK2(cs, cs_postponed);
5252
return (mapObjects.count(nHash) == 1 || mapPostponedObjects.count(nHash) == 1);
5353
}
5454

5555
bool CGovernanceManager::SerializeObjectForHash(const uint256& nHash, CDataStream& ss) const
5656
{
57-
LOCK(cs);
57+
LOCK2(cs, cs_postponed);
5858
auto it = mapObjects.find(nHash);
5959
if (it == mapObjects.end()) {
6060
it = mapPostponedObjects.find(nHash);
@@ -143,15 +143,17 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& msg_typ
143143
return;
144144
}
145145

146-
LOCK2(cs_main, cs);
146+
bool fRateCheckBypassed{false};
147+
{
148+
LOCK2(cs, cs_postponed);
147149

148-
if (mapObjects.count(nHash) || mapPostponedObjects.count(nHash) || mapErasedGovernanceObjects.count(nHash)) {
149-
// TODO - print error code? what if it's GOVOBJ_ERROR_IMMATURE?
150-
LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- Received already seen object: %s\n", strHash);
151-
return;
150+
if (mapObjects.count(nHash) || mapPostponedObjects.count(nHash) || mapErasedGovernanceObjects.count(nHash)) {
151+
// TODO - print error code? what if it's GOVOBJ_ERROR_IMMATURE?
152+
LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- Received already seen object: %s\n", strHash);
153+
return;
154+
}
152155
}
153156

154-
bool fRateCheckBypassed = false;
155157
if (!MasternodeRateCheck(govobj, true, false, fRateCheckBypassed)) {
156158
LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- masternode rate check failed - %s - (current block height %d) \n", strHash, nCachedBlockHeight);
157159
return;
@@ -175,6 +177,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& msg_typ
175177
} else {
176178
LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- Governance object is invalid - %s\n", strError);
177179
// apply node's ban score
180+
LOCK(cs_main);
178181
Misbehaving(pfrom->GetId(), 20);
179182
}
180183

@@ -230,6 +233,8 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& msg_typ
230233

231234
void CGovernanceManager::CheckOrphanVotes(CGovernanceObject& govobj, CConnman& connman)
232235
{
236+
LOCK(cs);
237+
233238
uint256 nHash = govobj.GetHash();
234239
std::vector<vote_time_pair_t> vecVotePairs;
235240
cmmapOrphanVotes.GetAll(nHash, vecVotePairs);
@@ -262,11 +267,9 @@ void CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj, CConnman
262267

263268
govobj.UpdateSentinelVariables(); //this sets local vars in object
264269

265-
LOCK2(cs_main, cs);
266-
std::string strError;
267-
268270
// MAKE SURE THIS OBJECT IS OK
269271

272+
std::string strError;
270273
if (!govobj.IsValidLocally(strError, true)) {
271274
LogPrint(BCLog::GOBJECT, "CGovernanceManager::AddGovernanceObject -- invalid governance object - %s - (nCachedBlockHeight %d) \n", strError, nCachedBlockHeight);
272275
return;
@@ -276,7 +279,7 @@ void CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj, CConnman
276279

277280
// INSERT INTO OUR GOVERNANCE OBJECT MEMORY
278281
// IF WE HAVE THIS OBJECT ALREADY, WE DON'T WANT ANOTHER COPY
279-
auto objpair = mapObjects.emplace(nHash, govobj);
282+
auto objpair = WITH_LOCK(cs, return mapObjects.emplace(nHash, govobj));
280283

281284
if (!objpair.second) {
282285
LogPrint(BCLog::GOBJECT, "CGovernanceManager::AddGovernanceObject -- already have governance object %s\n", nHash.ToString());
@@ -321,7 +324,7 @@ void CGovernanceManager::UpdateCachesAndClean()
321324

322325
std::vector<uint256> vecDirtyHashes = mmetaman.GetAndClearDirtyGovernanceObjectHashes();
323326

324-
LOCK2(cs_main, cs);
327+
LOCK(cs);
325328

326329
for (const uint256& nHash : vecDirtyHashes) {
327330
auto it = mapObjects.find(nHash);
@@ -534,6 +537,7 @@ bool CGovernanceManager::ConfirmInventoryRequest(const CInv& inv)
534537
// First check if we've already recorded this object
535538
switch (inv.type) {
536539
case MSG_GOVERNANCE_OBJECT: {
540+
LOCK(cs_postponed);
537541
if (mapObjects.count(inv.hash) == 1 || mapPostponedObjects.count(inv.hash) == 1) {
538542
LogPrint(BCLog::GOBJECT, "CGovernanceManager::ConfirmInventoryRequest already have governance object, returning false\n");
539543
return false;
@@ -836,8 +840,8 @@ void CGovernanceManager::CheckPostponedObjects(CConnman& connman)
836840
{
837841
if (!masternodeSync.IsSynced()) return;
838842

839-
LOCK2(cs_main, cs);
840-
843+
{
844+
LOCK(cs_postponed);
841845
// Check postponed proposals
842846
for (auto it = mapPostponedObjects.begin(); it != mapPostponedObjects.end();) {
843847
const uint256& nHash = it->first;
@@ -863,7 +867,9 @@ void CGovernanceManager::CheckPostponedObjects(CConnman& connman)
863867
// remove processed or invalid object from the queue
864868
mapPostponedObjects.erase(it++);
865869
}
870+
} // LOCK(cs_postponed)
866871

872+
LOCK(cs);
867873

868874
// Perform additional relays for triggers
869875
int64_t nNow = GetAdjustedTime();

src/governance/governance.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,9 @@ class CGovernanceManager
174174
// value - expiration time for deleted objects
175175
std::map<uint256, int64_t> mapErasedGovernanceObjects;
176176

177-
std::map<uint256, CGovernanceObject> mapPostponedObjects;
177+
mutable CCriticalSection cs_postponed;
178+
std::map<uint256, CGovernanceObject> mapPostponedObjects GUARDED_BY(cs_postponed);
179+
178180
hash_s_t setAdditionalRelayObjects;
179181

180182
object_ref_cm_t cmapVoteToObject;
@@ -316,7 +318,7 @@ class CGovernanceManager
316318

317319
void AddPostponedObject(const CGovernanceObject& govobj)
318320
{
319-
LOCK(cs);
321+
LOCK(cs_postponed);
320322
mapPostponedObjects.insert(std::make_pair(govobj.GetHash(), govobj));
321323
}
322324

src/governance/object.cpp

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,6 @@ UniValue CGovernanceObject::ToJson() const
438438

439439
void CGovernanceObject::UpdateLocalValidity()
440440
{
441-
LOCK(cs_main);
442441
// THIS DOES NOT CHECK COLLATERAL, THIS IS CHECKED UPON ORIGINAL ARRIVAL
443442
fCachedLocalValidity = IsValidLocally(strLocalValidityError, false);
444443
}
@@ -453,8 +452,6 @@ bool CGovernanceObject::IsValidLocally(std::string& strError, bool fCheckCollate
453452

454453
bool CGovernanceObject::IsValidLocally(std::string& strError, bool& fMissingConfirmations, bool fCheckCollateral) const
455454
{
456-
AssertLockHeld(cs_main);
457-
458455
fMissingConfirmations = false;
459456

460457
if (fUnparsable) {
@@ -464,7 +461,7 @@ bool CGovernanceObject::IsValidLocally(std::string& strError, bool& fMissingConf
464461

465462
switch (nObjectType) {
466463
case GOVERNANCE_OBJECT_PROPOSAL: {
467-
bool fAllowScript = (VersionBitsTipState(Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024) == ThresholdState::ACTIVE);
464+
bool fAllowScript = WITH_LOCK(cs_main, return VersionBitsTipState(Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024) == ThresholdState::ACTIVE);
468465
bool fAllowLegacyFormat = !fAllowScript; // reusing the same bit to stop accepting proposals in legacy format
469466
CProposalValidator validator(GetDataAsHexString(), fAllowLegacyFormat, fAllowScript);
470467
// Note: It's ok to have expired proposals
@@ -558,8 +555,8 @@ bool CGovernanceObject::IsCollateralValid(std::string& strError, bool& fMissingC
558555
CScript findScript;
559556
findScript << OP_RETURN << ToByteVector(nExpectedHash);
560557

561-
AssertLockHeld(cs_main);
562-
bool fork_active = VersionBitsState(LookupBlockIndex(nBlockHash), Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024, versionbitscache) == ThresholdState::ACTIVE;
558+
const CBlockIndex* pindex = WITH_LOCK(cs_main, return LookupBlockIndex(nBlockHash));
559+
bool fork_active = WITH_LOCK(cs_main, return VersionBitsState(pindex, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024, versionbitscache) == ThresholdState::ACTIVE);
563560
CAmount nMinFee = GetMinCollateralFee(fork_active);
564561

565562
LogPrint(BCLog::GOBJECT, "CGovernanceObject::IsCollateralValid -- txCollateral->vout.size() = %s, findScript = %s, nMinFee = %lld\n",
@@ -587,13 +584,9 @@ bool CGovernanceObject::IsCollateralValid(std::string& strError, bool& fMissingC
587584

588585
// GET CONFIRMATIONS FOR TRANSACTION
589586

590-
AssertLockHeld(cs_main);
591587
int nConfirmationsIn = 0;
592-
if (nBlockHash != uint256()) {
593-
const CBlockIndex* pindex = LookupBlockIndex(nBlockHash);
594-
if (pindex && ::ChainActive().Contains(pindex)) {
595-
nConfirmationsIn += ::ChainActive().Height() - pindex->nHeight + 1;
596-
}
588+
if (::ChainActive().Contains(pindex)) {
589+
nConfirmationsIn += ::ChainActive().Height() - pindex->nHeight + 1;
597590
}
598591

599592
if (nConfirmationsIn < GOVERNANCE_FEE_CONFIRMATIONS) {

src/governance/object.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,12 +240,12 @@ class CGovernanceObject
240240

241241
// CORE OBJECT FUNCTIONS
242242

243-
bool IsValidLocally(std::string& strError, bool fCheckCollateral) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
243+
bool IsValidLocally(std::string& strError, bool fCheckCollateral) const;
244244

245-
bool IsValidLocally(std::string& strError, bool& fMissingConfirmations, bool fCheckCollateral) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
245+
bool IsValidLocally(std::string& strError, bool& fMissingConfirmations, bool fCheckCollateral) const;
246246

247247
/// Check the collateral transaction for the budget proposal/finalized budget
248-
bool IsCollateralValid(std::string& strError, bool& fMissingConfirmations) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
248+
bool IsCollateralValid(std::string& strError, bool& fMissingConfirmations) const;
249249

250250
void UpdateLocalValidity();
251251

src/qt/governancelist.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ QString Proposal::url() const { return m_url; }
6464

6565
bool Proposal::isActive() const
6666
{
67-
LOCK(cs_main);
6867
std::string strError;
6968
return govObj.IsValidLocally(strError, false);
7069
}

src/rpc/governance.cpp

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,10 @@ static UniValue gobject_prepare(const JSONRPCRequest& request)
188188
request.params[3].getValStr(), request.params[4].getValStr(),
189189
govobj.GetDataAsPlainString(), govobj.GetHash().ToString());
190190

191+
bool fDIP0024IsActive = WITH_LOCK(cs_main, return VersionBitsTipState(Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024) == ThresholdState::ACTIVE);
191192
if (govobj.GetObjectType() == GOVERNANCE_OBJECT_PROPOSAL) {
192-
LOCK(cs_main);
193-
bool fAllowScript = (VersionBitsTipState(Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024) == ThresholdState::ACTIVE);
194193
// Note: we do not allow legacy format in RPC already, no need to reuse DEPLOYMENT_DIP0024
195-
CProposalValidator validator(strDataHex, false, fAllowScript);
194+
CProposalValidator validator(strDataHex, false, fDIP0024IsActive);
196195
if (!validator.Validate()) {
197196
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid proposal data, error messages:" + validator.GetErrorMessages());
198197
}
@@ -208,11 +207,9 @@ static UniValue gobject_prepare(const JSONRPCRequest& request)
208207

209208
LOCK(pwallet->cs_wallet);
210209

211-
{
212-
LOCK(cs_main);
213-
std::string strError = "";
214-
if (!govobj.IsValidLocally(strError, false))
215-
throw JSONRPCError(RPC_INTERNAL_ERROR, "Governance object is not valid - " + govobj.GetHash().ToString() + " - " + strError);
210+
std::string strError = "";
211+
if (!govobj.IsValidLocally(strError, false)) {
212+
throw JSONRPCError(RPC_INTERNAL_ERROR, "Governance object is not valid - " + govobj.GetHash().ToString() + " - " + strError);
216213
}
217214

218215
// If specified, spend this outpoint as the proposal fee
@@ -229,9 +226,7 @@ static UniValue gobject_prepare(const JSONRPCRequest& request)
229226

230227
CTransactionRef tx;
231228

232-
bool fork_active = VersionBitsTipState(Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024) == ThresholdState::ACTIVE;
233-
234-
if (!pwallet->GetBudgetSystemCollateralTX(tx, govobj.GetHash(), govobj.GetMinCollateralFee(fork_active), outpoint)) {
229+
if (!pwallet->GetBudgetSystemCollateralTX(tx, govobj.GetHash(), govobj.GetMinCollateralFee(fDIP0024IsActive), outpoint)) {
235230
std::string err = "Error making collateral transaction for governance object. Please check your wallet balance and make sure your wallet is unlocked.";
236231
if (!request.params[6].isNull() && !request.params[7].isNull()) {
237232
err += "Please verify your specified output is valid and is enough for the combined proposal fee and transaction fee.";
@@ -363,8 +358,7 @@ static UniValue gobject_submit(const JSONRPCRequest& request)
363358
govobj.GetDataAsPlainString(), govobj.GetHash().ToString(), txidFee.ToString());
364359

365360
if (govobj.GetObjectType() == GOVERNANCE_OBJECT_PROPOSAL) {
366-
LOCK(cs_main);
367-
bool fAllowScript = (VersionBitsTipState(Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024) == ThresholdState::ACTIVE);
361+
bool fAllowScript = WITH_LOCK(cs_main, return VersionBitsTipState(Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024) == ThresholdState::ACTIVE);
368362
// Note: we do not allow legacy format in RPC already, no need to reuse DEPLOYMENT_DIP0024
369363
CProposalValidator validator(strDataHex, false, fAllowScript);
370364
if (!validator.Validate()) {
@@ -389,18 +383,15 @@ static UniValue gobject_submit(const JSONRPCRequest& request)
389383

390384
std::string strHash = govobj.GetHash().ToString();
391385

386+
if (g_txindex) {
387+
g_txindex->BlockUntilSyncedToCurrentChain();
388+
}
389+
392390
std::string strError = "";
393391
bool fMissingConfirmations;
394-
{
395-
if (g_txindex) {
396-
g_txindex->BlockUntilSyncedToCurrentChain();
397-
}
398-
399-
LOCK(cs_main);
400-
if (!govobj.IsValidLocally(strError, fMissingConfirmations, true) && !fMissingConfirmations) {
401-
LogPrintf("gobject(submit) -- Object submission rejected because object is not valid - hash = %s, strError = %s\n", strHash, strError);
402-
throw JSONRPCError(RPC_INTERNAL_ERROR, "Governance object is not valid - " + strHash + " - " + strError);
403-
}
392+
if (!govobj.IsValidLocally(strError, fMissingConfirmations, true) && !fMissingConfirmations) {
393+
LogPrintf("gobject(submit) -- Object submission rejected because object is not valid - hash = %s, strError = %s\n", strHash, strError);
394+
throw JSONRPCError(RPC_INTERNAL_ERROR, "Governance object is not valid - " + strHash + " - " + strError);
404395
}
405396

406397
// RELAY THIS OBJECT
@@ -724,7 +715,7 @@ static UniValue ListObjects(const std::string& strCachedSignal, const std::strin
724715
g_txindex->BlockUntilSyncedToCurrentChain();
725716
}
726717

727-
LOCK2(cs_main, governance.cs);
718+
LOCK(governance.cs);
728719

729720
std::vector<CGovernanceObject> objs = governance.GetAllNewerThan(nStartTime);
730721
governance.UpdateLastDiffTime(GetTime());
@@ -867,7 +858,7 @@ static UniValue gobject_get(const JSONRPCRequest& request)
867858
}
868859

869860
// FIND THE GOVERNANCE OBJECT THE USER IS LOOKING FOR
870-
LOCK2(cs_main, governance.cs);
861+
LOCK(governance.cs);
871862
CGovernanceObject* pGovObj = governance.FindGovernanceObject(hash);
872863

873864
if (pGovObj == nullptr) {
@@ -1182,14 +1173,13 @@ static UniValue getgovernanceinfo(const JSONRPCRequest& request)
11821173
}
11831174

11841175
int nLastSuperblock = 0, nNextSuperblock = 0;
1185-
const auto* pindex = WITH_LOCK(cs_main, return ::ChainActive().Tip());
1186-
int nBlockHeight = pindex->nHeight;
1176+
const auto* pindex = ::ChainActive().Tip();
1177+
bool fork_active = WITH_LOCK(cs_main, return VersionBitsState(pindex, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024, versionbitscache) == ThresholdState::ACTIVE);
11871178

1188-
CSuperblock::GetNearestSuperblocksHeights(nBlockHeight, nLastSuperblock, nNextSuperblock);
1179+
CSuperblock::GetNearestSuperblocksHeights(pindex->nHeight, nLastSuperblock, nNextSuperblock);
11891180

11901181
UniValue obj(UniValue::VOBJ);
11911182
obj.pushKV("governanceminquorum", Params().GetConsensus().nGovernanceMinQuorum);
1192-
bool fork_active = VersionBitsState(pindex, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024, versionbitscache) == ThresholdState::ACTIVE;
11931183
obj.pushKV("proposalfee", ValueFromAmount(fork_active ? GOVERNANCE_PROPOSAL_FEE_TX : GOVERNANCE_PROPOSAL_FEE_TX_OLD));
11941184
obj.pushKV("superblockcycle", Params().GetConsensus().nSuperblockCycle);
11951185
obj.pushKV("lastsuperblock", nLastSuperblock);

0 commit comments

Comments
 (0)