-
Notifications
You must be signed in to change notification settings - Fork 1.2k
refactor: separate network and consensus logic 3/N [governance] #7008
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
✅ No Merge Conflicts DetectedThis PR currently has no conflicts with other open PRs. |
WalkthroughThe PR refactors governance networking by introducing NetGovernance as a NetHandler and centralizing handler scheduling via PeerManager::ScheduleHandlers. CGovernanceManager's network-facing API is simplified (ProcessMessage → ProcessObject) and new accessors added (FetchRelayInventory, FetchGovernanceObjectVotes, GetMNManager, ProcessVote) with updated locking annotations. NetHandler gains Schedule and ProcessMessage now accepts a CConnman& parameter. CMasternodeSync's governance tick/maintenance code is removed. LoadChainstate signatures drop governance/txindex/network-id parameters. Tests and lint expectations adjusted for changed dependency graph. Sequence Diagram(s)sequenceDiagram
participant Scheduler
participant PeerManager
participant NetGovernance
participant CGovernanceManager
participant Connman
participant Node
Note over Scheduler,PeerManager: Handler registration
Scheduler->>PeerManager: ScheduleHandlers()
PeerManager->>NetGovernance: Schedule(scheduler, connman)
Note over Scheduler,NetGovernance: Periodic processing
Scheduler->>NetGovernance: ProcessTick(connman)
alt Need votes/objects
NetGovernance->>CGovernanceManager: FetchGovernanceObjectVotes(...)
NetGovernance->>Connman: send object/vote requests
else Relay/housekeeping
NetGovernance->>CGovernanceManager: FetchRelayInventory()
end
Note over Node,NetGovernance: Incoming messages
PeerManager->>NetGovernance: ProcessMessage(node, connman, msg_type, vRecv)
alt MNGOVERNANCEOBJECT
NetGovernance->>CGovernanceManager: ProcessObject(node, hash, govobj)
else MNGOVERNANCEOBJECTVOTE
NetGovernance->>CGovernanceManager: ProcessVote(node, vote, exception, connman)
end
NetGovernance->>PeerManager: PeerPostProcessMessage(result)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (9)
src/net_processing.cpp (1)
662-662: ClarifyPeerPostProcessMessagesemantics for Node-scoped side effects
PeerPostProcessMessagealways callsPostProcessMessage(std::move(ret), -1), so anym_error/m_to_eraseinMessageProcessingResultwill not be attributed to a real peer (bothMisbehavingandEraseObjectRequesteffectively no-op for node-1).If NetHandlers are expected to:
- Drive misbehavior scoring or
- Erase per-peer object requests
via
MessageProcessingResult, they will currently not get those behaviors when going throughPeerPostProcessMessage. In that case, either:
- Thread the actual
NodeIdthroughPeerPostProcessMessage, or- Document that handlers must call
PeerMisbehaving/PeerEraseObjectRequestdirectly and only usePeerPostProcessMessagefor node-agnostic actions (m_transactions,m_inventory,m_dsq).Please confirm which contract you intend and adjust either the API or callers accordingly.
Also applies to: 3587-3604, 6579-6582
src/governance/net_governance.cpp (7)
20-20: Unnecessary forward declaration.
CConnmanis already declared innet.hwhich is included on line 12. This forward declaration is redundant.-class CConnman; - void NetGovernance::Schedule(CScheduler& scheduler, CConnman& connman)
131-131: Minor typo: "to early" → "too early".- // to early to ask the same node + // too early to ask the same node
161-162: Minor style: preferstatic constoverconst static.Both are valid C++, but
static constis the more conventional ordering.- const static int64_t nSyncStart = TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now()); - const static std::string strAllow = strprintf("allow-sync-%lld", nSyncStart); + static const int64_t nSyncStart = TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now()); + static const std::string strAllow = strprintf("allow-sync-%lld", nSyncStart);
310-310: Minor typo: "to early" → "too early".- continue; // to early for this node + continue; // too early for this node
379-382: RedundantIsBlockchainSynced()check.This check is redundant because line 348 already returns early if
!m_node_sync.IsBlockchainSynced(). Consider removing for clarity.- if (!m_node_sync.IsBlockchainSynced()) { - LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- masternode list not synced\n"); - return; - }
409-412: RedundantIsBlockchainSynced()check.Same as above - this is already guarded by the check on line 348.
- if (!m_node_sync.IsBlockchainSynced()) { - LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECTVOTE -- masternode list not synced\n"); - return; - }
440-441: Existing TODO comment about relay issue.This TODO indicates a known issue with immediate inventory relay. Consider tracking this in an issue if not already done.
Would you like me to help document this issue or investigate why immediate sending doesn't work here?
src/governance/governance.h (1)
389-389: Minor: extra blank line.bool ProcessVote(CNode* pfrom, const CGovernanceVote& vote, CGovernanceException& exception, CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(!cs_store); - private:
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (17)
src/Makefile.am(2 hunks)src/governance/governance.cpp(9 hunks)src/governance/governance.h(1 hunks)src/governance/net_governance.cpp(1 hunks)src/governance/net_governance.h(1 hunks)src/init.cpp(3 hunks)src/instantsend/net_instantsend.cpp(1 hunks)src/instantsend/net_instantsend.h(1 hunks)src/masternode/sync.cpp(1 hunks)src/masternode/sync.h(2 hunks)src/net_processing.cpp(5 hunks)src/net_processing.h(3 hunks)src/node/chainstate.cpp(0 hunks)src/node/chainstate.h(0 hunks)src/test/util/setup_common.cpp(0 hunks)src/validation.h(0 hunks)test/lint/lint-circular-dependencies.py(2 hunks)
💤 Files with no reviewable changes (4)
- src/test/util/setup_common.cpp
- src/validation.h
- src/node/chainstate.h
- src/node/chainstate.cpp
🧰 Additional context used
📓 Path-based instructions (6)
src/**/*.{cpp,h,hpp,cc}
📄 CodeRabbit inference engine (CLAUDE.md)
Dash Core implementation must be written in C++20, requiring at least Clang 16 or GCC 11.1
Files:
src/masternode/sync.cppsrc/governance/net_governance.hsrc/instantsend/net_instantsend.cppsrc/governance/governance.cppsrc/masternode/sync.hsrc/net_processing.hsrc/instantsend/net_instantsend.hsrc/init.cppsrc/net_processing.cppsrc/governance/net_governance.cppsrc/governance/governance.h
src/{masternode,evo}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Masternode lists must use immutable data structures (Immer library) for thread safety
Files:
src/masternode/sync.cppsrc/masternode/sync.h
src/{masternode,evo,llmq,governance,coinjoin}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Dash-specific database implementations: CFlatDB for persistent storage (MasternodeMetaStore, GovernanceStore, SporkStore, NetFulfilledRequestStore) and CDBWrapper extensions for Evolution/DKG/InstantSend/Quorum/RecoveredSigs data
Files:
src/masternode/sync.cppsrc/governance/net_governance.hsrc/governance/governance.cppsrc/masternode/sync.hsrc/governance/net_governance.cppsrc/governance/governance.h
src/{masternode,llmq}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
BLS integration must be used for cryptographic foundation of advanced masternode features
Files:
src/masternode/sync.cppsrc/masternode/sync.h
src/{masternode,llmq,evo,coinjoin,governance}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Use unordered_lru_cache for efficient caching with LRU eviction in Dash-specific data structures
Files:
src/masternode/sync.cppsrc/governance/net_governance.hsrc/governance/governance.cppsrc/masternode/sync.hsrc/governance/net_governance.cppsrc/governance/governance.h
src/governance/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
Files:
src/governance/net_governance.hsrc/governance/governance.cppsrc/governance/net_governance.cppsrc/governance/governance.h
🧠 Learnings (21)
📓 Common learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/llmq/utils.cpp:284-298
Timestamp: 2025-11-04T18:24:27.241Z
Learning: In consensus-critical code (such as quorum formation, block validation, or deployment activation logic), do not suggest changes to the logic itself even if the implementation appears theoretically incorrect or off-by-one. Consensus rules, once deployed on the Dash network, must be preserved exactly to avoid network forks. Refactoring PRs should maintain perfect behavioral equivalence. Only suggest logic changes if explicitly accompanied by a DIP (Dash Improvement Proposal) or if the maintainer indicates the consensus rule needs to be changed with appropriate activation logic.
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/governance/**/*.{cpp,h} : Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/governance/**/*.{cpp,h} : Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
Applied to files:
src/Makefile.amsrc/masternode/sync.cppsrc/governance/net_governance.hsrc/governance/governance.cppsrc/masternode/sync.hsrc/init.cppsrc/governance/net_governance.cppsrc/governance/governance.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,txmempool}/**/*.{cpp,h} : Block validation and mempool handling must use extensions to Bitcoin Core mechanisms for special transaction validation and enhanced transaction relay
Applied to files:
src/Makefile.amsrc/governance/governance.cppsrc/masternode/sync.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,consensus,net_processing}/**/*.{cpp,h} : ValidationInterface callbacks must be used for event-driven architecture to coordinate subsystems during block/transaction processing
Applied to files:
src/Makefile.amsrc/governance/governance.cppsrc/net_processing.hsrc/governance/governance.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/evo/evodb/**/*.{cpp,h} : Evolution Database (CEvoDb) must handle masternode snapshots, quorum state, governance objects with efficient differential updates for masternode lists
Applied to files:
src/masternode/sync.cppsrc/governance/governance.cppsrc/masternode/sync.hsrc/init.cppsrc/governance/governance.h
📚 Learning: 2025-09-09T21:36:58.969Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:223-232
Timestamp: 2025-09-09T21:36:58.969Z
Learning: In RawSender class (src/stats/rawsender.cpp), socket operations are properly synchronized using the cs_net mutex. The m_sock and m_server members are GUARDED_BY(cs_net), and methods like Connect(), SendDirectly(), and ReconnectThread() use appropriate locking with cs_net to prevent race conditions on socket access.
Applied to files:
src/instantsend/net_instantsend.cpp
📚 Learning: 2025-09-09T21:36:31.504Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:31.504Z
Learning: In RawSender class (src/stats/rawsender.cpp), m_sock access requires synchronization using the cs_net mutex. The race condition exists between SendDirectly() (callable from any thread) and Connect() (called by ReconnectThread), where both read and write m_sock concurrently. The cs_net mutex properly coordinates these network operations.
Applied to files:
src/instantsend/net_instantsend.cpp
📚 Learning: 2025-09-09T21:36:11.833Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:11.833Z
Learning: In RawSender class (src/stats/rawsender.cpp), cs_net is the appropriate mutex for protecting socket access (m_sock) and network operations, not additional custom locks. The implementation correctly uses cs_net with GUARDED_BY annotations and EXCLUSIVE_LOCKS_REQUIRED to synchronize socket access between SendDirectly() and ReconnectThread().
Applied to files:
src/instantsend/net_instantsend.cppsrc/governance/governance.h
📚 Learning: 2025-09-09T21:36:31.504Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:31.504Z
Learning: In RawSender class (src/stats/rawsender.cpp), m_sock access is protected by the cs_net mutex. This mutex coordinates between the TCP send path in SendDirectly() and the reconnection operations in Connect()/Reconnect() methods, ensuring proper synchronization of socket state.
Applied to files:
src/instantsend/net_instantsend.cpp
📚 Learning: 2025-09-09T21:36:11.833Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:11.833Z
Learning: In RawSender class (src/stats/rawsender.cpp), cs_net is the appropriate mutex for protecting socket access (m_sock) and network operations, not additional custom locks.
Applied to files:
src/instantsend/net_instantsend.cpp
📚 Learning: 2025-09-09T21:36:58.969Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:223-232
Timestamp: 2025-09-09T21:36:58.969Z
Learning: In RawSender class (src/stats/rawsender.cpp), socket access operations (m_sock and m_server) should be protected by the cs_net mutex, not avoiding synchronization entirely. While lock overhead concerns are valid in general, socket operations require proper synchronization via cs_net.
Applied to files:
src/instantsend/net_instantsend.cpp
📚 Learning: 2025-10-21T11:09:34.688Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6849
File: src/governance/governance.cpp:1339-1343
Timestamp: 2025-10-21T11:09:34.688Z
Learning: In PR #6849, `cmapVoteToObject` was intentionally moved from `GovernanceStore` to `CGovernanceManager` as a memory-only variable and is NOT guarded by `cs_store`. It relies on `CacheMap`'s internal thread-safety instead.
Applied to files:
src/governance/governance.cppsrc/governance/governance.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{masternode,llmq}/**/*.{cpp,h} : BLS integration must be used for cryptographic foundation of advanced masternode features
Applied to files:
src/governance/governance.cppsrc/masternode/sync.hsrc/init.cpp
📚 Learning: 2025-10-28T08:54:00.392Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6926
File: test/functional/feature_governance_cl.py:0-0
Timestamp: 2025-10-28T08:54:00.392Z
Learning: In Dash tests, the scheduler (mockscheduler) operates independently of network state. Isolated nodes should still run scheduler-based cleanup processes like governance cleanup, even if they have different state due to network isolation.
Applied to files:
src/governance/governance.cppsrc/init.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/coinjoin/**/*.{cpp,h} : CoinJoin implementation must use masternode-coordinated mixing sessions with uniform denomination outputs
Applied to files:
src/masternode/sync.h
📚 Learning: 2025-11-04T18:23:28.175Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/governance/classes.cpp:147-154
Timestamp: 2025-11-04T18:23:28.175Z
Learning: In src/governance/classes.cpp, CSuperblock::GetPaymentsLimit intentionally uses synthetic difficulty constants (nBits = 1 for mainnet, powLimit for networks with min difficulty) and simple height-based V20 activation checks instead of actual chain block data. This is by design because superblocks themselves are "synthetic" governance payment blocks, not regular mined blocks.
Applied to files:
src/masternode/sync.hsrc/governance/governance.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{masternode,evo,llmq,governance,coinjoin}/**/*.{cpp,h} : Use Dash-specific database implementations: CFlatDB for persistent storage (MasternodeMetaStore, GovernanceStore, SporkStore, NetFulfilledRequestStore) and CDBWrapper extensions for Evolution/DKG/InstantSend/Quorum/RecoveredSigs data
Applied to files:
src/masternode/sync.hsrc/init.cppsrc/governance/governance.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/node/chainstate.{cpp,h} : Chainstate initialization must be separated into dedicated src/node/chainstate.* files
Applied to files:
src/init.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/evo/**/*.{cpp,h} : Special transactions use payload serialization routines defined in src/evo/specialtx.h and must include appropriate special transaction types (ProRegTx, ProUpServTx, ProUpRegTx, ProUpRevTx)
Applied to files:
src/init.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/llmq/**/*.{cpp,h} : InstantSend implementation must provide distributed key generation for secure transaction locking with quorum consensus
Applied to files:
src/init.cpp
📚 Learning: 2025-11-13T20:02:55.480Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6969
File: src/evo/deterministicmns.h:441-479
Timestamp: 2025-11-13T20:02:55.480Z
Learning: In `src/evo/deterministicmns.h`, the `internalId` field in `CDeterministicMN` and the `mnInternalIdMap` in `CDeterministicMNList` are non-deterministic and used only for internal bookkeeping and efficient lookups. Different nodes can assign different internalIds to the same masternode depending on their sync history. Methods like `IsEqual()` intentionally ignore internalId mappings and only compare consensus-critical deterministic fields (proTxHash, collateral, state, etc.).
Applied to files:
src/governance/governance.h
🧬 Code graph analysis (7)
src/governance/net_governance.h (3)
src/governance/governance.cpp (2)
CGovernanceManager(66-79)CGovernanceManager(81-85)src/net_processing.h (3)
NetHandler(71-87)NetHandler(75-78)PeerManagerInternal(58-69)src/governance/net_governance.cpp (10)
Schedule(22-54)Schedule(22-22)ProcessMessage(345-449)ProcessMessage(345-345)SendGovernanceSyncRequest(56-61)SendGovernanceSyncRequest(56-56)RequestGovernanceObjectVotes(63-152)RequestGovernanceObjectVotes(63-63)ProcessTick(154-343)ProcessTick(154-154)
src/instantsend/net_instantsend.cpp (1)
src/net_processing.cpp (12)
ProcessMessage(3681-5471)ProcessMessage(3681-3686)pfrom(618-618)pfrom(639-640)pfrom(753-755)pfrom(764-764)pfrom(772-772)pfrom(775-775)pfrom(777-777)pfrom(779-779)pfrom(875-875)pfrom(1057-1057)
src/governance/governance.cpp (2)
src/governance/governance.h (1)
nCachedBlockHeight(261-261)src/net.h (1)
FullyConnectedOnly(1296-1296)
src/net_processing.h (1)
src/net_processing.cpp (26)
PeerGetRequestedObjectCount(6574-6577)PeerGetRequestedObjectCount(6574-6574)nodeid(628-628)nodeid(631-631)nodeid(644-644)nodeid(656-656)nodeid(661-661)nodeid(679-679)nodeid(681-681)nodeid(719-720)nodeid(730-730)nodeid(862-862)nodeid(864-864)nodeid(1040-1040)nodeid(1075-1075)PeerPostProcessMessage(6579-6582)PeerPostProcessMessage(6579-6579)ret(662-662)ret(685-685)scheduler(624-624)scheduler(652-652)scheduler(694-694)ProcessMessage(3681-5471)ProcessMessage(3681-3686)ScheduleHandlers(1701-1706)ScheduleHandlers(1701-1701)
src/instantsend/net_instantsend.h (2)
src/net_processing.cpp (12)
ProcessMessage(3681-5471)ProcessMessage(3681-3686)pfrom(618-618)pfrom(639-640)pfrom(753-755)pfrom(764-764)pfrom(772-772)pfrom(775-775)pfrom(777-777)pfrom(779-779)pfrom(875-875)pfrom(1057-1057)src/instantsend/net_instantsend.cpp (2)
ProcessMessage(17-65)ProcessMessage(17-17)
src/init.cpp (3)
src/interfaces/node.h (2)
node(42-44)node(404-404)src/rpc/blockchain.h (1)
node(33-36)src/init.h (1)
node(23-25)
src/governance/net_governance.cpp (3)
src/util/time.h (1)
TicksSinceEpoch(86-89)src/net.h (1)
FullyConnectedOnly(1296-1296)src/masternode/sync.cpp (2)
ProcessMessage(99-112)ProcessMessage(99-99)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: linux64_tsan-build / Build source
- GitHub Check: x86_64-w64-mingw32 / Build depends
- GitHub Check: Lint / Run linters
- GitHub Check: x86_64-pc-linux-gnu_nowallet / Build depends
- GitHub Check: x86_64-apple-darwin / Build depends
- GitHub Check: x86_64-pc-linux-gnu / Build depends
- GitHub Check: arm-linux-gnueabihf / Build depends
🔇 Additional comments (29)
src/Makefile.am (1)
222-223: Net governance unit correctly wired into build systemAdding
governance/net_governance.htoBITCOIN_CORE_Handgovernance/net_governance.cpptolibbitcoin_node_a_SOURCESis consistent with how other governance components are exposed and linked; no issues from a build/ordering perspective.Also applies to: 511-511
src/instantsend/net_instantsend.h (1)
34-38: NetInstantSend interface aligned with NetHandler and Stop/Interrupt contractUpdating
ProcessMessageto acceptCConnman&and adding anInterrupt()override that forwards toworkInterrupt()cleanly integrates NetInstantSend with the new NetHandler interface and the existingStop()assertion that expectsInterrupt()to be called first. No functional regressions apparent.src/instantsend/net_instantsend.cpp (1)
17-17: ProcessMessage signature update is consistent and behavior‑preservingThe implementation now takes
CConnman&(unnamed) to match the updated NetHandler interface and net_processing call sites, while leaving the message handling logic unchanged. This maintains existing InstantSend behavior.src/net_processing.cpp (3)
1701-1706: Handler scheduling loop is straightforward and thread-safe
ScheduleHandlersjust iteratesm_handlersand forwardsschedulerandm_connman; there are no new locking or lifecycle hazards here given handlers are already managed viaStart/Stop/Interrupt.
5462-5463: EnsureNetHandler::ProcessMessage’s contract matches ignoring its return value
handler->ProcessMessage(pfrom, m_connman, msg_type, vRecv);is now called for eachm_handlersentry, and its return value (if any) is ignored, unlike the built-in handlers above which still funnel theirMessageProcessingResultthroughPostProcessMessage.Please verify that:
NetHandler::ProcessMessagehas been changed tovoid(handlers do their own post-processing viaPeer*APIs), or- If it still returns a
MessageProcessingResult, that all relevant logic was migrated into the handlers and no behavior previously driven by the result is now lost.If the latter, consider restoring a
PostProcessMessagecall on the result to keep the behavior consistent.
652-652: Scheduling API surface is cohesive with existing handler lifecycleAdding
ScheduleHandlers(CScheduler&)alongsideStartHandlers/StopHandlers/InterruptHandlersmaintains a clear responsibility split: construction, lifecycle, and periodic scheduling are all delegated throughPeerManagerImpl. The current design keeps handler ownership and scheduling concerns centralized.Also applies to: 1670-1699
src/masternode/sync.cpp (1)
7-8: Includes updated to match used typesAdding
<chain.h>and<net.h>is appropriate here given this implementation usesCBlockIndex,CConnman, andCNode. This tightens dependencies without changing behavior.src/init.cpp (2)
2229-2229: LGTM! NetGovernance handler correctly wired.The handler is properly constructed with required dependencies and added after loading the governance cache. This follows the same pattern as
NetInstantSendon line 2198.Note: The
NetGovernance::ProcessMessageandNetGovernance::Scheduleimplementations already checkm_gov_manager.IsValid()internally (persrc/governance/net_governance.cpplines 23 and 344), so the handler can be safely added regardless ofis_governance_enabled.
2301-2301: Centralized scheduling viaScheduleHandlersis a clean refactor.This replaces governance-specific scheduling with a generalized mechanism that iterates over all registered
NetHandlerinstances and calls theirSchedulemethod. This improves separation of concerns.src/net_processing.h (3)
67-68: Appropriate extension ofPeerManagerInternalinterface.These methods expose necessary peer-level operations to
NetHandlerimplementations:
PeerGetRequestedObjectCount: Allows handlers to check request queue size to preventsetAskForoverflow (used inRequestGovernanceObjectVotes)PeerPostProcessMessage: Enables handlers to trigger post-processing for misbehavior trackingBoth are properly implemented in
PeerManagerImplper the relevant snippets.
83-84:NetHandlerinterface extended with scheduling and message processing hooks.Adding
CConnman¶meter to both methods is necessary for handlers to send network messages. The default empty implementations allow handlers to opt-in to only the functionality they need.
174-174:ScheduleHandlersprovides centralized scheduling orchestration.This completes the
PeerManagerinterface to support the new handler scheduling pattern used ininit.cpp.src/governance/net_governance.h (1)
1-39: Well-structured newNetGovernancehandler class.The design cleanly separates governance networking concerns:
- Proper inheritance from
NetHandlerwithfinalspecifier- Constructor dependency injection pattern matches the codebase style
- References (not pointers) for required dependencies ensure non-null invariants
- Private helpers encapsulate implementation details
Minor observation: The include guard uses
BITCOIN_GOVERNANCE_NET_GOVERNANCE_Hwhich follows the existing convention in the codebase.test/lint/lint-circular-dependencies.py (2)
42-43: Circular dependency expectations correctly updated.The paths now route through
governance/governancedirectly instead of viamasternode/active/context, reflecting the architectural change where governance networking is decoupled from the active masternode context.
53-53: The new circular dependency is a necessary consequence of the design, not unintended.The cycle exists because
CMasternodeSynchas aCConnman&member variable (sync.h line 52) and calls methods on it in the implementation, requiringsync.cppto include the fullnet.hdefinition. Conversely, multiple functions inCConnmantakeCMasternodeSync¶meters and appear to require the full definition, necessitating the include innet.cpp. This tight coupling is the minimal expected dependency given the architectural choice to embedCConnman&inCMasternodeSync. No refactoring is needed unless the underlying architecture changes.src/masternode/sync.h (2)
22-28: Sync state constants properly exposed.Moving these constants to the header allows
NetGovernanceand other components to reference sync states and timing values without duplicating magic numbers. The values are well-documented with comments.
67-73: New accessors enable external governance sync management.These additions expose the minimum necessary internal state:
BumpAttempt(): AllowsNetGovernanceto track peer attemptsGetLastBump(): Enables timeout checking in external schedulingIsReachedBestHeader(): Required for sync state decisionsThis is a good pattern - exposing controlled accessors rather than making members public or passing the entire object.
src/governance/net_governance.cpp (3)
22-54: LGTM!The scheduling logic correctly gates governance-specific tasks behind
IsValid()and uses appropriate timing for test vs. production environments.
94-96: Static local state requires careful consideration.Using
staticlocals forcs_recentlyandmapAskedRecentlymeans this state persists across allNetGovernanceinstances and is shared globally. While this appears intentional (to track recently-asked peers across sync sessions), ensure this is the desired behavior, especially if multipleNetGovernanceinstances could exist.
140-147: Verify loop termination when no nodes can be asked.The
i--on line 146 compensates whenfAskedis false, but since lines 141-145 unconditionally pop from the vectors regardless offAsked, the loop will eventually terminate when vectors empty (line 116 breaks). This logic appears correct but is subtle.src/governance/governance.cpp (8)
27-27: LGTM!Include change from
validation.htovalidationinterface.haligns with the PR's goal of separating concerns. The file usesGetMainSignals()fromvalidationinterface.hfor notifications.
183-231: LGTM with optional efficiency note.The new
ProcessObjectmethod correctly consolidates governance object processing. The lock annotations properly requirecs_mainto be held by the caller (as shown innet_governance.cppline 393 withWITH_LOCK(::cs_main, ...)).For a future optimization, consider taking
CGovernanceObjectby rvalue reference since it's ultimately moved into storage, but this is fine for a refactoring PR.
449-455: LGTM!Clean swap-and-return pattern for fetching relay inventory with proper locking.
599-599: LGTM!Adding explicit
LOCK(cs_store)at function start correctly implements the lock requirement for accessingmapObjects.
652-652: LGTM!Same as above - proper lock acquisition for
SyncObjects.
960-960: LGTM!
GetMNManager()correctly usesAssertto ensurem_dmnmanis valid before dereferencing.
962-991: LGTM!The updated
FetchGovernanceObjectVotesreturns a structured pair of vectors, providing a cleaner API than modifying parameters in-place.
1174-1198: LGTM!The orphan vote cleanup logic is correctly inlined, and the
NodesSnapshotpattern withFullyConnectedOnlymatches usage inProcessTick()(seenet_governance.cppline 179).src/governance/governance.h (1)
367-388: LGTM! Clear API section for NetGovernance integration.The new public methods are well-organized under a clear comment and have proper lock annotations. The API surface exposed to
NetGovernanceis appropriately scoped:
FetchRelayInventory()- relay coordinationCheckAndRemove()- cleanup operationsRequestOrphanObjects()- orphan managementFetchGovernanceObjectVotes()- vote request preparationProcessObject()/ProcessVote()- object/vote processingSyncObjects()/SyncSingleObjVotes()- sync responsesAcceptMessage()- request trackingGetMNManager()- MN list access
| /** Default for -syncmempool */ | ||
| static const bool DEFAULT_SYNC_MEMPOOL = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
DEFAULT_SYNC_MEMPOOL constant placement.
This constant is now defined in the masternode/sync header. Verify this is the intended location, as it appears to be a general node configuration option rather than masternode-specific.
🏁 Script executed:
#!/bin/bash
# Check where DEFAULT_SYNC_MEMPOOL was previously defined and where it's used
rg -n "DEFAULT_SYNC_MEMPOOL" --type cpp --type hLength of output: 383
I'll verify whether this location is appropriate by checking the pattern for similar configuration constants.
Actually, let me correct that - I need to search the actual codebase:
🏁 Script executed:
#!/bin/bash
# Check pattern of DEFAULT_* constants and their locations
echo "=== Finding DEFAULT_* constants ==="
rg -n "static const.*DEFAULT_" --type cpp --type h | head -20
echo ""
echo "=== Checking what init.cpp includes for constants ==="
rg -n "^#include" src/init.cpp | head -20
echo ""
echo "=== Checking where other mempool constants are defined ==="
rg -n "mempool" --type h src/ | grep -i "const\|define" | head -15Length of output: 4544
🏁 Script executed:
This will be run on the codebase to check patterns.Length of output: 42
🏁 Script executed:
#!/bin/bash
# Check pattern of DEFAULT_* constants and their locations
echo "=== Finding DEFAULT_* constants ==="
rg -n "static const.*DEFAULT_" --type cpp --type h | head -20
echo ""
echo "=== Checking what init.cpp includes ==="
head -50 src/init.cpp | rg "^#include"
echo ""
echo "=== Check other DEFAULT_ constants in masternode/sync.h and nearby files ==="
rg -n "DEFAULT_" src/masternode/ --type cpp --type h | head -15Length of output: 2768
Let me check if this constant was recently added or moved to this location.
🏁 Script executed:
#!/bin/bash
# Check if validation.h is included by masternode/sync.h or other related files
echo "=== Checking masternode/sync.h includes ==="
head -30 src/masternode/sync.h
echo ""
echo "=== Check validation.h for mempool-related constants ==="
rg -n "DEFAULT_.*MEMPOOL|DEFAULT_.*SYNC" src/validation.h
echo ""
echo "=== Look for any other instances of DEFAULT_SYNC in codebase ==="
rg -n "DEFAULT_SYNC" --type cpp --type hLength of output: 1813
Move DEFAULT_SYNC_MEMPOOL to src/validation.h with other mempool-related defaults.
The constant is placed in src/masternode/sync.h but should follow the established pattern: similar mempool constants like DEFAULT_MEMPOOL_EXPIRY and DEFAULT_PERSIST_MEMPOOL are defined in src/validation.h. The -syncmempool option is a general node configuration (used in src/init.cpp) and governance (src/governance/net_governance.cpp), not masternode-specific functionality. This placement should be moved to maintain proper separation of concerns and code organization.
🤖 Prompt for AI Agents
In src/masternode/sync.h around lines 17-18, the DEFAULT_SYNC_MEMPOOL constant
belongs in src/validation.h with the other mempool defaults; remove the static
const bool DEFAULT_SYNC_MEMPOOL = true; from sync.h, add the same definition
into src/validation.h next to DEFAULT_MEMPOOL_EXPIRY/DEFAULT_PERSIST_MEMPOOL,
and ensure any files that previously relied on including sync.h for this symbol
(e.g., src/init.cpp, src/governance/net_governance.cpp) include src/validation.h
instead; rebuild to verify no missing symbol or include errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's correct; the file masternode/sync.h which have CMasternodeSync is incorrectly named and incorrectly placed. It has nothing to do with "masternode".
It should be called NodeSyncing or NodeSyncStatus or something similar and be located in node/sync.h.
DEFAULT_SYNC_MEMPOOL is correctly located now. it has nothing to do with "validation" in validation.h
Renaming it is out-of-scope of this PR; could be done someday later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@knst, thank you for the clarification! You're absolutely right that DEFAULT_SYNC_MEMPOOL belongs with the synchronization logic conceptually, not with validation. I understand now that while the file naming and location could be improved (as a future refactoring to node/sync.h with a class rename), the constant is correctly co-located with the sync functionality it relates to.
I appreciate you explaining the architectural reasoning—this helps me better understand the separation between sync-related configuration and validation-related configuration.
(\__/)
(='.'=) *noted for future reviews*
(")_(")
✏️ Learnings added
Learnt from: knst
Repo: dashpay/dash PR: 7008
File: src/masternode/sync.h:17-18
Timestamp: 2025-11-25T10:53:37.501Z
Learning: In Dash Core, `DEFAULT_SYNC_MEMPOOL` belongs with node synchronization logic (currently in src/masternode/sync.h) rather than with validation logic in src/validation.h, even though other mempool-related constants are in validation.h. The constant is conceptually tied to sync functionality, not validation.
Learnt from: knst
Repo: dashpay/dash PR: 7008
File: src/masternode/sync.h:17-18
Timestamp: 2025-11-25T10:53:37.501Z
Learning: The file src/masternode/sync.h containing `CMasternodeSync` is misnamed and misplaced—it has nothing to do with "masternode" functionality. It should eventually be renamed to `NodeSyncing` or `NodeSyncStatus` and moved to src/node/sync.h as a future refactoring.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/evo/evodb/**/*.{cpp,h} : Evolution Database (CEvoDb) must handle masternode snapshots, quorum state, governance objects with efficient differential updates for masternode lists
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,txmempool}/**/*.{cpp,h} : Block validation and mempool handling must use extensions to Bitcoin Core mechanisms for special transaction validation and enhanced transaction relay
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/governance/**/*.{cpp,h} : Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/llmq/utils.cpp:284-298
Timestamp: 2025-11-04T18:24:27.241Z
Learning: In consensus-critical code (such as quorum formation, block validation, or deployment activation logic), do not suggest changes to the logic itself even if the implementation appears theoretically incorrect or off-by-one. Consensus rules, once deployed on the Dash network, must be preserved exactly to avoid network forks. Refactoring PRs should maintain perfect behavioral equivalence. Only suggest logic changes if explicitly accompanied by a DIP (Dash Improvement Proposal) or if the maintainer indicates the consensus rule needs to be changed with appropriate activation logic.
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CMasternodeSync is incorrectly named and incorrectly placed. It has nothing to do with "masternode".
To provide some historical context: it was originally used to sync masternode list before DIP0003 and before any governance code existed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
src/net_processing.cpp
Outdated
| void PeerRelayInvFiltered(const CInv& inv, const CTransaction& relatedTx) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); | ||
| void PeerRelayInvFiltered(const CInv& inv, const uint256& relatedTxHash) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); | ||
| void PeerAskPeersForTransaction(const uint256& txid) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); | ||
| size_t PeerGetRequestedObjectCount(NodeId nodeid) const override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix missing cs_main lock in PeerGetRequestedObjectCount wrapper
GetRequestedObjectCount asserts cs_main and reads m_node_states (GUARDED_BY(cs_main)), but PeerGetRequestedObjectCount calls it without taking cs_main, which will:
- Trip
AssertLockHeld(cs_main)in debug builds. - Cause a data race on
m_node_statesin release builds.
Wrap the call in a cs_main lock (and keep the !m_peer_mutex precondition to preserve lock order), e.g.:
size_t PeerManagerImpl::PeerGetRequestedObjectCount(NodeId nodeid) const
{
- return GetRequestedObjectCount(nodeid);
+ WITH_LOCK(cs_main, return GetRequestedObjectCount(nodeid));
}This aligns the wrapper with the callee’s locking contract.
Also applies to: 1650-1658, 6574-6577
🤖 Prompt for AI Agents
In src/net_processing.cpp around line 661 (and similarly at 1650-1658 and
6574-6577), the PeerGetRequestedObjectCount wrapper calls
GetRequestedObjectCount without holding cs_main even though
GetRequestedObjectCount asserts cs_main and reads m_node_states
(GUARDED_BY(cs_main)); update each wrapper to acquire cs_main while preserving
the existing !m_peer_mutex precondition/lock ordering, call
GetRequestedObjectCount while cs_main is held, then release cs_main before
returning so the wrapper satisfies the callee’s locking contract and avoids
assert/data-race.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cs_main is hold correctly, see:
WITH_LOCK(::cs_main, m_peer_manager->PeerEraseObjectRequest(peer.GetId(), CInv{MSG_GOVERNANCE_OBJECT, nHash}));
Annotation exists also:
void PeerEraseObjectRequest(const NodeId nodeid, const CInv& inv) override EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@knst Thanks for the clarification — agreed on PeerEraseObjectRequest: it’s annotated EXCLUSIVE_LOCKS_REQUIRED(::cs_main) and the call site holds cs_main.
The concern I raised is specifically about PeerGetRequestedObjectCount. Its interface is only EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex), but it calls GetRequestedObjectCount(), which asserts cs_main and reads m_node_states (GUARDED_BY(cs_main)). Since callers of PeerGetRequestedObjectCount are not required to hold cs_main, this can trip the AssertLockHeld(cs_main) in debug or race in release.
Minimal, safe fix (preserves the existing precondition and lock ordering):
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
@@
size_t PeerManagerImpl::PeerGetRequestedObjectCount(NodeId nodeid) const
{
- return GetRequestedObjectCount(nodeid);
+ // Wrapper does not require cs_main; the callee asserts cs_main.
+ // Take cs_main here to satisfy the callee’s locking contract while keeping
+ // the !m_peer_mutex precondition and lock order intact.
+ WITH_LOCK(::cs_main, return GetRequestedObjectCount(nodeid));
}If you prefer the alternative of making cs_main an explicit requirement for the wrapper, we can also tighten the annotation in the interface to EXCLUSIVE_LOCKS_REQUIRED(::cs_main, !m_peer_mutex) and adjust call sites accordingly. Let me know which direction you’d like; I can update the patch.
🧠 Learnings used
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:223-232
Timestamp: 2025-09-09T21:36:58.969Z
Learning: In RawSender class (src/stats/rawsender.cpp), socket access operations (m_sock and m_server) should be protected by the cs_net mutex, not avoiding synchronization entirely. While lock overhead concerns are valid in general, socket operations require proper synchronization via cs_net.
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:11.833Z
Learning: In RawSender class (src/stats/rawsender.cpp), cs_net is the appropriate mutex for protecting socket access (m_sock) and network operations, not additional custom locks. The implementation correctly uses cs_net with GUARDED_BY annotations and EXCLUSIVE_LOCKS_REQUIRED to synchronize socket access between SendDirectly() and ReconnectThread().
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/llmq/utils.cpp:284-298
Timestamp: 2025-11-04T18:24:27.241Z
Learning: In consensus-critical code (such as quorum formation, block validation, or deployment activation logic), do not suggest changes to the logic itself even if the implementation appears theoretically incorrect or off-by-one. Consensus rules, once deployed on the Dash network, must be preserved exactly to avoid network forks. Refactoring PRs should maintain perfect behavioral equivalence. Only suggest logic changes if explicitly accompanied by a DIP (Dash Improvement Proposal) or if the maintainer indicates the consensus rule needs to be changed with appropriate activation logic.
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
dc1d437 to
094a3f6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (4)
src/governance/net_governance.cpp (3)
20-20: Redundant forward declaration.
CConnmanis already included transitively through the headers. This forward declaration is unnecessary.-class CConnman; - void NetGovernance::Schedule(CScheduler& scheduler, CConnman& connman)
131-132: Typo: "to early" should be "too early".- // to early to ask the same node + // too early to ask the same node if (mapAskedRecently[nHashGovobj].count(pnode->addr)) continue;
154-171: Static local variables limit testability.The static variables (
nTick,nSyncStart,strAllow,nTimeLastProcess) persist across calls and would be shared if multipleNetGovernanceinstances existed. This limits unit test isolation.Consider promoting these to member variables in a follow-up PR to improve testability, though this is acceptable for a refactoring PR focused on code movement.
src/governance/governance.cpp (1)
183-231: Consider adding lock assertion for clarity.The method is declared with
EXCLUSIVE_LOCKS_REQUIRED(::cs_main, ...)and is correctly called withcs_mainheld inNetGovernance::ProcessMessage. However, adding an explicit assertion at the method entry would make the requirement self-documenting and catch misuse earlier (before the assertion inAddGovernanceObjectInternal).bool CGovernanceManager::ProcessObject(const CNode& peer, const uint256& nHash, CGovernanceObject govobj) { + AssertLockHeld(::cs_main); std::string strHash = nHash.ToString(); LOCK(cs_store);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/governance/governance.cpp(9 hunks)src/governance/governance.h(1 hunks)src/governance/net_governance.cpp(1 hunks)src/governance/net_governance.h(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
src/**/*.{cpp,h,hpp,cc}
📄 CodeRabbit inference engine (CLAUDE.md)
Dash Core implementation must be written in C++20, requiring at least Clang 16 or GCC 11.1
Files:
src/governance/net_governance.cppsrc/governance/net_governance.hsrc/governance/governance.cppsrc/governance/governance.h
src/{masternode,evo,llmq,governance,coinjoin}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Dash-specific database implementations: CFlatDB for persistent storage (MasternodeMetaStore, GovernanceStore, SporkStore, NetFulfilledRequestStore) and CDBWrapper extensions for Evolution/DKG/InstantSend/Quorum/RecoveredSigs data
Files:
src/governance/net_governance.cppsrc/governance/net_governance.hsrc/governance/governance.cppsrc/governance/governance.h
src/governance/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
Files:
src/governance/net_governance.cppsrc/governance/net_governance.hsrc/governance/governance.cppsrc/governance/governance.h
src/{masternode,llmq,evo,coinjoin,governance}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Use unordered_lru_cache for efficient caching with LRU eviction in Dash-specific data structures
Files:
src/governance/net_governance.cppsrc/governance/net_governance.hsrc/governance/governance.cppsrc/governance/governance.h
🧠 Learnings (12)
📓 Common learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/llmq/utils.cpp:284-298
Timestamp: 2025-11-04T18:24:27.241Z
Learning: In consensus-critical code (such as quorum formation, block validation, or deployment activation logic), do not suggest changes to the logic itself even if the implementation appears theoretically incorrect or off-by-one. Consensus rules, once deployed on the Dash network, must be preserved exactly to avoid network forks. Refactoring PRs should maintain perfect behavioral equivalence. Only suggest logic changes if explicitly accompanied by a DIP (Dash Improvement Proposal) or if the maintainer indicates the consensus rule needs to be changed with appropriate activation logic.
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/governance/**/*.{cpp,h} : Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/governance/**/*.{cpp,h} : Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
Applied to files:
src/governance/net_governance.cppsrc/governance/net_governance.hsrc/governance/governance.cppsrc/governance/governance.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,consensus,net_processing}/**/*.{cpp,h} : ValidationInterface callbacks must be used for event-driven architecture to coordinate subsystems during block/transaction processing
Applied to files:
src/governance/net_governance.cppsrc/governance/governance.cppsrc/governance/governance.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/evo/evodb/**/*.{cpp,h} : Evolution Database (CEvoDb) must handle masternode snapshots, quorum state, governance objects with efficient differential updates for masternode lists
Applied to files:
src/governance/governance.cppsrc/governance/governance.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{masternode,llmq}/**/*.{cpp,h} : BLS integration must be used for cryptographic foundation of advanced masternode features
Applied to files:
src/governance/governance.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,txmempool}/**/*.{cpp,h} : Block validation and mempool handling must use extensions to Bitcoin Core mechanisms for special transaction validation and enhanced transaction relay
Applied to files:
src/governance/governance.cpp
📚 Learning: 2025-10-28T08:54:00.392Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6926
File: test/functional/feature_governance_cl.py:0-0
Timestamp: 2025-10-28T08:54:00.392Z
Learning: In Dash tests, the scheduler (mockscheduler) operates independently of network state. Isolated nodes should still run scheduler-based cleanup processes like governance cleanup, even if they have different state due to network isolation.
Applied to files:
src/governance/governance.cpp
📚 Learning: 2025-10-21T11:09:34.688Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6849
File: src/governance/governance.cpp:1339-1343
Timestamp: 2025-10-21T11:09:34.688Z
Learning: In PR #6849, `cmapVoteToObject` was intentionally moved from `GovernanceStore` to `CGovernanceManager` as a memory-only variable and is NOT guarded by `cs_store`. It relies on `CacheMap`'s internal thread-safety instead.
Applied to files:
src/governance/governance.cppsrc/governance/governance.h
📚 Learning: 2025-11-13T20:02:55.480Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6969
File: src/evo/deterministicmns.h:441-479
Timestamp: 2025-11-13T20:02:55.480Z
Learning: In `src/evo/deterministicmns.h`, the `internalId` field in `CDeterministicMN` and the `mnInternalIdMap` in `CDeterministicMNList` are non-deterministic and used only for internal bookkeeping and efficient lookups. Different nodes can assign different internalIds to the same masternode depending on their sync history. Methods like `IsEqual()` intentionally ignore internalId mappings and only compare consensus-critical deterministic fields (proTxHash, collateral, state, etc.).
Applied to files:
src/governance/governance.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{masternode,evo,llmq,governance,coinjoin}/**/*.{cpp,h} : Use Dash-specific database implementations: CFlatDB for persistent storage (MasternodeMetaStore, GovernanceStore, SporkStore, NetFulfilledRequestStore) and CDBWrapper extensions for Evolution/DKG/InstantSend/Quorum/RecoveredSigs data
Applied to files:
src/governance/governance.h
📚 Learning: 2025-09-09T21:36:11.833Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:11.833Z
Learning: In RawSender class (src/stats/rawsender.cpp), cs_net is the appropriate mutex for protecting socket access (m_sock) and network operations, not additional custom locks. The implementation correctly uses cs_net with GUARDED_BY annotations and EXCLUSIVE_LOCKS_REQUIRED to synchronize socket access between SendDirectly() and ReconnectThread().
Applied to files:
src/governance/governance.h
📚 Learning: 2025-11-04T18:23:28.175Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/governance/classes.cpp:147-154
Timestamp: 2025-11-04T18:23:28.175Z
Learning: In src/governance/classes.cpp, CSuperblock::GetPaymentsLimit intentionally uses synthetic difficulty constants (nBits = 1 for mainnet, powLimit for networks with min difficulty) and simple height-based V20 activation checks instead of actual chain block data. This is by design because superblocks themselves are "synthetic" governance payment blocks, not regular mined blocks.
Applied to files:
src/governance/governance.h
🧬 Code graph analysis (3)
src/governance/net_governance.h (4)
src/governance/governance.cpp (2)
CGovernanceManager(66-79)CGovernanceManager(81-85)src/masternode/sync.cpp (4)
CMasternodeSync(14-20)CMasternodeSync(22-22)ProcessMessage(99-112)ProcessMessage(99-99)src/net_processing.h (3)
NetHandler(71-87)NetHandler(75-78)PeerManagerInternal(58-69)src/governance/net_governance.cpp (10)
Schedule(22-54)Schedule(22-22)ProcessMessage(345-449)ProcessMessage(345-345)SendGovernanceSyncRequest(56-61)SendGovernanceSyncRequest(56-56)RequestGovernanceObjectVotes(63-152)RequestGovernanceObjectVotes(63-63)ProcessTick(154-343)ProcessTick(154-154)
src/governance/governance.cpp (2)
src/governance/governance.h (1)
nCachedBlockHeight(261-261)src/coinjoin/client.h (1)
nCachedBlockHeight(264-264)
src/governance/governance.h (2)
src/governance/governance.cpp (10)
FetchRelayInventory(449-455)FetchRelayInventory(449-449)AcceptMessage(993-1005)AcceptMessage(993-993)ProcessObject(183-231)ProcessObject(183-183)GetMNManager(960-960)GetMNManager(960-960)ProcessVote(800-858)ProcessVote(800-800)src/governance/object.cpp (2)
ProcessVote(58-159)ProcessVote(58-59)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: linux64_tsan-build / Build source
- GitHub Check: x86_64-apple-darwin / Build depends
- GitHub Check: Lint / Run linters
- GitHub Check: x86_64-w64-mingw32 / Build depends
- GitHub Check: x86_64-pc-linux-gnu_nowallet / Build depends
- GitHub Check: x86_64-pc-linux-gnu / Build depends
- GitHub Check: arm-linux-gnueabihf / Build depends
🔇 Additional comments (6)
src/governance/net_governance.h (1)
14-37: Clean NetHandler implementation for governance networking.The
NetGovernanceclass properly derives fromNetHandlerand follows the established pattern for network handlers. The dependency injection via constructor references is appropriate, and the interface is well-defined.src/governance/net_governance.cpp (2)
22-54: Well-structured scheduling with appropriate guards.The scheduling logic properly:
- Checks
ShutdownRequested()before processing ticks- Conditionally schedules housekeeping only when governance is valid
- Uses different timing for test vs. production networks
345-448: Governance message handling properly migrated.The
ProcessMessagemethod correctly handles all three governance message types with appropriate validation and peer misbehavior scoring. TheProcessObjectcall at line 393 properly acquirescs_mainviaWITH_LOCKas required by the method's lock annotations.src/governance/governance.cpp (2)
449-455: Efficient swap-based inventory transfer.Using
swapto transfer the relay inventory avoids unnecessary copying while atomically clearing the source vector under the lock.
1174-1188: Good addition of orphan vote cleanup.The orphan vote cleanup properly removes expired entries before requesting objects, preventing accumulation of stale data. The iterator handling correctly saves the current position before advancing.
src/governance/governance.h (1)
367-388: Well-organized public API expansion for NetGovernance.The new public methods are properly grouped with a clarifying comment and have consistent lock annotations that match their implementations. The separation of governance networking concerns into
NetGovernancewhile exposing necessary accessors maintains good encapsulation.
094a3f6 to
a5ef0da
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (3)
src/governance/governance.cpp (1)
183-231: Clarify locking expectations forProcessObject(cs_main precondition).
ProcessObjectassumes::cs_mainis held by the caller (as done inNetGovernance::ProcessMessageviaWITH_LOCK(::cs_main, ...)) but only lockscs_storelocally. This works with current call sites and keepsAddGovernanceObjectInternal’s lock assertions satisfied, but nothing in this method enforces thecs_mainprecondition.To future‑proof against accidental misuse, consider adding an
AssertLockHeld(::cs_main);at the top ofProcessObjectand documenting that it must be called withcs_mainheld. Behavior stays identical, but incorrect future call sites will fail fast in debug builds.src/instantsend/net_instantsend.cpp (1)
17-65: ProcessMessage signature alignment looks good.Updating
NetInstantSend::ProcessMessageto takeCConnman&matches the newNetHandlerinterface andPeerManagerdispatch. The unused parameter is fine; if compiler warnings become noisy, you can mark it[[maybe_unused]]or name it and(void)connman;, but that’s optional.src/governance/governance.h (1)
389-390: Minor: Extra blank line.There's an extra blank line before the
private:section that could be removed for consistency.bool ProcessVote(CNode* pfrom, const CGovernanceVote& vote, CGovernanceException& exception, CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(!cs_store); - private:
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (17)
src/Makefile.am(2 hunks)src/governance/governance.cpp(9 hunks)src/governance/governance.h(1 hunks)src/governance/net_governance.cpp(1 hunks)src/governance/net_governance.h(1 hunks)src/init.cpp(3 hunks)src/instantsend/net_instantsend.cpp(1 hunks)src/instantsend/net_instantsend.h(1 hunks)src/masternode/sync.cpp(1 hunks)src/masternode/sync.h(2 hunks)src/net_processing.cpp(5 hunks)src/net_processing.h(3 hunks)src/node/chainstate.cpp(0 hunks)src/node/chainstate.h(0 hunks)src/test/util/setup_common.cpp(0 hunks)src/validation.h(0 hunks)test/lint/lint-circular-dependencies.py(2 hunks)
💤 Files with no reviewable changes (4)
- src/node/chainstate.cpp
- src/node/chainstate.h
- src/test/util/setup_common.cpp
- src/validation.h
🚧 Files skipped from review as they are similar to previous changes (3)
- src/instantsend/net_instantsend.h
- src/Makefile.am
- src/masternode/sync.cpp
🧰 Additional context used
📓 Path-based instructions (6)
src/**/*.{cpp,h,hpp,cc}
📄 CodeRabbit inference engine (CLAUDE.md)
Dash Core implementation must be written in C++20, requiring at least Clang 16 or GCC 11.1
Files:
src/net_processing.hsrc/instantsend/net_instantsend.cppsrc/governance/net_governance.hsrc/governance/net_governance.cppsrc/init.cppsrc/governance/governance.cppsrc/governance/governance.hsrc/masternode/sync.hsrc/net_processing.cpp
src/{masternode,evo,llmq,governance,coinjoin}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Dash-specific database implementations: CFlatDB for persistent storage (MasternodeMetaStore, GovernanceStore, SporkStore, NetFulfilledRequestStore) and CDBWrapper extensions for Evolution/DKG/InstantSend/Quorum/RecoveredSigs data
Files:
src/governance/net_governance.hsrc/governance/net_governance.cppsrc/governance/governance.cppsrc/governance/governance.hsrc/masternode/sync.h
src/governance/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
Files:
src/governance/net_governance.hsrc/governance/net_governance.cppsrc/governance/governance.cppsrc/governance/governance.h
src/{masternode,llmq,evo,coinjoin,governance}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Use unordered_lru_cache for efficient caching with LRU eviction in Dash-specific data structures
Files:
src/governance/net_governance.hsrc/governance/net_governance.cppsrc/governance/governance.cppsrc/governance/governance.hsrc/masternode/sync.h
src/{masternode,evo}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Masternode lists must use immutable data structures (Immer library) for thread safety
Files:
src/masternode/sync.h
src/{masternode,llmq}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
BLS integration must be used for cryptographic foundation of advanced masternode features
Files:
src/masternode/sync.h
🧠 Learnings (30)
📓 Common learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/llmq/utils.cpp:284-298
Timestamp: 2025-11-04T18:24:27.241Z
Learning: In consensus-critical code (such as quorum formation, block validation, or deployment activation logic), do not suggest changes to the logic itself even if the implementation appears theoretically incorrect or off-by-one. Consensus rules, once deployed on the Dash network, must be preserved exactly to avoid network forks. Refactoring PRs should maintain perfect behavioral equivalence. Only suggest logic changes if explicitly accompanied by a DIP (Dash Improvement Proposal) or if the maintainer indicates the consensus rule needs to be changed with appropriate activation logic.
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/governance/**/*.{cpp,h} : Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,consensus,net_processing}/**/*.{cpp,h} : ValidationInterface callbacks must be used for event-driven architecture to coordinate subsystems during block/transaction processing
Applied to files:
src/net_processing.hsrc/governance/net_governance.cppsrc/governance/governance.cppsrc/governance/governance.h
📚 Learning: 2025-09-09T21:36:58.969Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:223-232
Timestamp: 2025-09-09T21:36:58.969Z
Learning: In RawSender class (src/stats/rawsender.cpp), socket operations are properly synchronized using the cs_net mutex. The m_sock and m_server members are GUARDED_BY(cs_net), and methods like Connect(), SendDirectly(), and ReconnectThread() use appropriate locking with cs_net to prevent race conditions on socket access.
Applied to files:
src/instantsend/net_instantsend.cpp
📚 Learning: 2025-09-09T21:36:31.504Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:31.504Z
Learning: In RawSender class (src/stats/rawsender.cpp), m_sock access requires synchronization using the cs_net mutex. The race condition exists between SendDirectly() (callable from any thread) and Connect() (called by ReconnectThread), where both read and write m_sock concurrently. The cs_net mutex properly coordinates these network operations.
Applied to files:
src/instantsend/net_instantsend.cpp
📚 Learning: 2025-09-09T21:36:11.833Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:11.833Z
Learning: In RawSender class (src/stats/rawsender.cpp), cs_net is the appropriate mutex for protecting socket access (m_sock) and network operations, not additional custom locks. The implementation correctly uses cs_net with GUARDED_BY annotations and EXCLUSIVE_LOCKS_REQUIRED to synchronize socket access between SendDirectly() and ReconnectThread().
Applied to files:
src/instantsend/net_instantsend.cppsrc/governance/governance.hsrc/net_processing.cpp
📚 Learning: 2025-09-09T21:36:31.504Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:31.504Z
Learning: In RawSender class (src/stats/rawsender.cpp), m_sock access is protected by the cs_net mutex. This mutex coordinates between the TCP send path in SendDirectly() and the reconnection operations in Connect()/Reconnect() methods, ensuring proper synchronization of socket state.
Applied to files:
src/instantsend/net_instantsend.cpp
📚 Learning: 2025-09-09T21:36:11.833Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:11.833Z
Learning: In RawSender class (src/stats/rawsender.cpp), cs_net is the appropriate mutex for protecting socket access (m_sock) and network operations, not additional custom locks.
Applied to files:
src/instantsend/net_instantsend.cpp
📚 Learning: 2025-09-09T21:36:58.969Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:223-232
Timestamp: 2025-09-09T21:36:58.969Z
Learning: In RawSender class (src/stats/rawsender.cpp), socket access operations (m_sock and m_server) should be protected by the cs_net mutex, not avoiding synchronization entirely. While lock overhead concerns are valid in general, socket operations require proper synchronization via cs_net.
Applied to files:
src/instantsend/net_instantsend.cppsrc/net_processing.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/governance/**/*.{cpp,h} : Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
Applied to files:
src/governance/net_governance.hsrc/governance/net_governance.cppsrc/init.cppsrc/governance/governance.cppsrc/governance/governance.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/node/chainstate.{cpp,h} : Chainstate initialization must be separated into dedicated src/node/chainstate.* files
Applied to files:
src/init.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/evo/evodb/**/*.{cpp,h} : Evolution Database (CEvoDb) must handle masternode snapshots, quorum state, governance objects with efficient differential updates for masternode lists
Applied to files:
src/init.cppsrc/governance/governance.cppsrc/governance/governance.hsrc/masternode/sync.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{masternode,evo,llmq,governance,coinjoin}/**/*.{cpp,h} : Use Dash-specific database implementations: CFlatDB for persistent storage (MasternodeMetaStore, GovernanceStore, SporkStore, NetFulfilledRequestStore) and CDBWrapper extensions for Evolution/DKG/InstantSend/Quorum/RecoveredSigs data
Applied to files:
src/init.cppsrc/governance/governance.hsrc/masternode/sync.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/evo/**/*.{cpp,h} : Special transactions use payload serialization routines defined in src/evo/specialtx.h and must include appropriate special transaction types (ProRegTx, ProUpServTx, ProUpRegTx, ProUpRevTx)
Applied to files:
src/init.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{masternode,llmq}/**/*.{cpp,h} : BLS integration must be used for cryptographic foundation of advanced masternode features
Applied to files:
src/init.cppsrc/governance/governance.cppsrc/masternode/sync.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/llmq/**/*.{cpp,h} : InstantSend implementation must provide distributed key generation for secure transaction locking with quorum consensus
Applied to files:
src/init.cpp
📚 Learning: 2025-10-28T08:54:00.392Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6926
File: test/functional/feature_governance_cl.py:0-0
Timestamp: 2025-10-28T08:54:00.392Z
Learning: In Dash tests, the scheduler (mockscheduler) operates independently of network state. Isolated nodes should still run scheduler-based cleanup processes like governance cleanup, even if they have different state due to network isolation.
Applied to files:
src/init.cppsrc/governance/governance.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,txmempool}/**/*.{cpp,h} : Block validation and mempool handling must use extensions to Bitcoin Core mechanisms for special transaction validation and enhanced transaction relay
Applied to files:
src/governance/governance.cppsrc/masternode/sync.h
📚 Learning: 2025-11-25T10:53:37.523Z
Learnt from: knst
Repo: dashpay/dash PR: 7008
File: src/masternode/sync.h:17-18
Timestamp: 2025-11-25T10:53:37.523Z
Learning: The file src/masternode/sync.h containing `CMasternodeSync` is misnamed and misplaced—it has nothing to do with "masternode" functionality. It should eventually be renamed to `NodeSyncing` or `NodeSyncStatus` and moved to src/node/sync.h as a future refactoring.
Applied to files:
src/governance/governance.cppsrc/masternode/sync.h
📚 Learning: 2025-11-25T10:53:37.523Z
Learnt from: knst
Repo: dashpay/dash PR: 7008
File: src/masternode/sync.h:17-18
Timestamp: 2025-11-25T10:53:37.523Z
Learning: In Dash Core, `DEFAULT_SYNC_MEMPOOL` belongs with node synchronization logic (currently in src/masternode/sync.h) rather than with validation logic in src/validation.h, even though other mempool-related constants are in validation.h. The constant is conceptually tied to sync functionality, not validation.
Applied to files:
src/governance/governance.cppsrc/masternode/sync.h
📚 Learning: 2025-10-21T11:09:34.688Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6849
File: src/governance/governance.cpp:1339-1343
Timestamp: 2025-10-21T11:09:34.688Z
Learning: In PR #6849, `cmapVoteToObject` was intentionally moved from `GovernanceStore` to `CGovernanceManager` as a memory-only variable and is NOT guarded by `cs_store`. It relies on `CacheMap`'s internal thread-safety instead.
Applied to files:
src/governance/governance.cppsrc/governance/governance.h
📚 Learning: 2025-11-13T20:02:55.480Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6969
File: src/evo/deterministicmns.h:441-479
Timestamp: 2025-11-13T20:02:55.480Z
Learning: In `src/evo/deterministicmns.h`, the `internalId` field in `CDeterministicMN` and the `mnInternalIdMap` in `CDeterministicMNList` are non-deterministic and used only for internal bookkeeping and efficient lookups. Different nodes can assign different internalIds to the same masternode depending on their sync history. Methods like `IsEqual()` intentionally ignore internalId mappings and only compare consensus-critical deterministic fields (proTxHash, collateral, state, etc.).
Applied to files:
src/governance/governance.h
📚 Learning: 2025-11-04T18:23:28.175Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/governance/classes.cpp:147-154
Timestamp: 2025-11-04T18:23:28.175Z
Learning: In src/governance/classes.cpp, CSuperblock::GetPaymentsLimit intentionally uses synthetic difficulty constants (nBits = 1 for mainnet, powLimit for networks with min difficulty) and simple height-based V20 activation checks instead of actual chain block data. This is by design because superblocks themselves are "synthetic" governance payment blocks, not regular mined blocks.
Applied to files:
src/governance/governance.hsrc/masternode/sync.h
📚 Learning: 2025-11-04T18:24:27.241Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/llmq/utils.cpp:284-298
Timestamp: 2025-11-04T18:24:27.241Z
Learning: In consensus-critical code (such as quorum formation, block validation, or deployment activation logic), do not suggest changes to the logic itself even if the implementation appears theoretically incorrect or off-by-one. Consensus rules, once deployed on the Dash network, must be preserved exactly to avoid network forks. Refactoring PRs should maintain perfect behavioral equivalence. Only suggest logic changes if explicitly accompanied by a DIP (Dash Improvement Proposal) or if the maintainer indicates the consensus rule needs to be changed with appropriate activation logic.
Applied to files:
src/masternode/sync.hsrc/net_processing.cpp
📚 Learning: 2025-06-09T16:43:20.996Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
Applied to files:
src/masternode/sync.hsrc/net_processing.cpp
📚 Learning: 2025-10-05T20:38:28.457Z
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.
Applied to files:
src/masternode/sync.h
📚 Learning: 2025-07-29T14:32:48.369Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.
Applied to files:
src/masternode/sync.hsrc/net_processing.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{masternode,llmq,evo,coinjoin,governance}/**/*.{cpp,h} : Use unordered_lru_cache for efficient caching with LRU eviction in Dash-specific data structures
Applied to files:
src/masternode/sync.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/coinjoin/**/*.{cpp,h} : CoinJoin implementation must use masternode-coordinated mixing sessions with uniform denomination outputs
Applied to files:
src/masternode/sync.h
📚 Learning: 2025-08-19T14:57:31.801Z
Learnt from: knst
Repo: dashpay/dash PR: 6692
File: src/llmq/blockprocessor.cpp:217-224
Timestamp: 2025-08-19T14:57:31.801Z
Learning: In PR #6692, knst acknowledged a null pointer dereference issue in ProcessBlock() method where LookupBlockIndex may return nullptr but is passed to gsl::not_null, and created follow-up PR #6789 to address it, consistent with avoiding scope creep in performance-focused PRs.
Applied to files:
src/net_processing.cpp
📚 Learning: 2025-07-29T14:33:01.040Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/wallet/wallet.cpp:0-0
Timestamp: 2025-07-29T14:33:01.040Z
Learning: In refactoring PRs like #6761, kwvg acknowledges code safety improvements (like null pointer checks and unused parameter warnings) but prefers to defer them to follow-up PRs to maintain focus on the primary refactoring objectives, avoiding scope creep.
Applied to files:
src/net_processing.cpp
🧬 Code graph analysis (7)
src/net_processing.h (1)
src/net_processing.cpp (36)
PeerGetRequestedObjectCount(6574-6577)PeerGetRequestedObjectCount(6574-6574)nodeid(628-628)nodeid(631-631)nodeid(644-644)nodeid(656-656)nodeid(661-661)nodeid(679-679)nodeid(681-681)nodeid(719-720)nodeid(730-730)nodeid(862-862)nodeid(864-864)nodeid(1040-1040)nodeid(1075-1075)PeerPostProcessMessage(6579-6582)PeerPostProcessMessage(6579-6579)ret(662-662)ret(685-685)scheduler(624-624)scheduler(652-652)scheduler(694-694)ProcessMessage(3681-5471)ProcessMessage(3681-3686)pfrom(618-618)pfrom(639-640)pfrom(753-755)pfrom(764-764)pfrom(772-772)pfrom(775-775)pfrom(777-777)pfrom(779-779)pfrom(875-875)pfrom(1057-1057)ScheduleHandlers(1701-1706)ScheduleHandlers(1701-1701)
src/instantsend/net_instantsend.cpp (1)
src/net_processing.cpp (12)
ProcessMessage(3681-5471)ProcessMessage(3681-3686)pfrom(618-618)pfrom(639-640)pfrom(753-755)pfrom(764-764)pfrom(772-772)pfrom(775-775)pfrom(777-777)pfrom(779-779)pfrom(875-875)pfrom(1057-1057)
src/governance/net_governance.h (2)
src/net_processing.h (3)
NetHandler(71-87)NetHandler(75-78)PeerManagerInternal(58-69)src/governance/net_governance.cpp (10)
Schedule(22-54)Schedule(22-22)ProcessMessage(345-449)ProcessMessage(345-345)SendGovernanceSyncRequest(56-61)SendGovernanceSyncRequest(56-56)RequestGovernanceObjectVotes(63-152)RequestGovernanceObjectVotes(63-63)ProcessTick(154-343)ProcessTick(154-154)
src/governance/net_governance.cpp (1)
src/net.h (1)
FullyConnectedOnly(1296-1296)
src/init.cpp (5)
src/net_processing.cpp (10)
node(616-616)node(617-617)node(642-642)node(757-757)node(792-792)node(892-896)node(907-907)node(918-918)node(929-929)node(937-937)src/interfaces/node.h (2)
node(42-44)node(404-404)src/kernel/coinstats.h (1)
node(19-21)src/rpc/blockchain.h (1)
node(33-36)src/init.h (1)
node(23-25)
src/governance/governance.cpp (1)
src/governance/governance.h (1)
nCachedBlockHeight(261-261)
src/masternode/sync.h (1)
src/masternode/sync.cpp (6)
BumpAssetLastTime(43-48)BumpAssetLastTime(43-43)GetAssetName(50-59)GetAssetName(50-50)GetSyncStatus(89-97)GetSyncStatus(89-89)
🔇 Additional comments (15)
src/net_processing.h (1)
58-69: Handler and peer APIs are consistent with the new scheduling/message flow.The additions to
PeerManagerInternal(PeerGetRequestedObjectCount,PeerPostProcessMessage),NetHandler(Schedule,ProcessMessagewithCConnman&), andPeerManager::ScheduleHandlersmatch the pattern implemented inPeerManagerImpland used byNetGovernance/NetInstantSend. The abstractions keep network plumbing insidePeerManagerwhile letting individual handlers own their scheduling and message handling.Also applies to: 71-87, 155-175
src/governance/net_governance.h (1)
14-37: NetGovernance handler design matches the refactoring goal.
NetGovernanceencapsulates governance P2P logic behind the genericNetHandlerinterface and is wired via constructor injection into the existing managers, which is exactly what’s needed to decouple governance consensus state fromPeerManager. TheSchedule/ProcessMessageoverrides match the base class and the implementation innet_governance.cpp.src/init.cpp (2)
88-92: NetGovernance attachment and gating look correct.
NetGovernanceis always added as an extra handler, butis_governance_enabledis still respected by only loading the governance cache when enabled, and the handler’s implementation guards work onm_gov_manager.IsValid()/ sync state. That keeps the wiring simple ininit.cppwhile avoiding governance network activity (and DB usage) when validation is disabled.Also applies to: 1690-1691, 2212-2229
2292-2302: Scheduler integration viaScheduleHandlersis a clean generalization.Calling
node.peerman->ScheduleHandlers(*node.scheduler);after registering all handlers (InstantSend, NetGovernance, etc.) centralizes their periodic work (governance cleanup, orphan requests, relay batching, etc.) behind the NetHandler abstraction instead of hard-coding per-subsystem schedule blocks ininit.cpp. The order relative to LLQM/masternode scheduling and the shutdown sequence is consistent with existing patterns.test/lint/lint-circular-dependencies.py (1)
41-53: Updated circular-dependency expectations are consistent with the new handler wiring.The added cycles capturing
core_io → evo/mnhftx → llmq/signing → net_processing → governance/* → core_ioandmasternode/sync → net → masternode/syncreflect the new NetGovernance/handler paths and sync wiring without changing the linter logic. The whitelist stays aligned with the current architecture.src/masternode/sync.h (1)
17-18: Sync constants and CMasternodeSync accessors are consistent with current design.Defining
DEFAULT_SYNC_MEMPOOLalongside other sync-related constants and exposingBumpAttempt(),GetLastBump(), andIsReachedBestHeader()mirrors the existing implementation insync.cppand keeps node-sync status queryable without changing behavior. Placement of the constant here matches the intended association with node synchronization rather than validation.Also applies to: 65-74
src/governance/governance.cpp (1)
449-455: LGTM on new relay/vote fetch helpers and orphan‑vote cleanup.
FetchRelayInventory()correctly batches and drainsm_relay_invsundercs_relay, called within scheduler-driven relay path inNetGovernance.FetchGovernanceObjectVotes()safely co-operates with externalNetGovernancecode by cleaning expiredmapAskedRecentlyentries using the advance-then-erase pattern while holdingcs_store, and honoringnPeersPerHashMaxbefore processing objects.RequestOrphanObjects()'s pruning loop overcmmapOrphanVotes.GetItemList()correctly removes expired orphan votes using the advance-then-erase pattern to avoid iterator invalidation before requesting.These changes improve separation between network handler code and governance state while maintaining scheduler-driven, network-decoupled voting architecture, without altering consensus behavior.
src/governance/net_governance.cpp (4)
22-54: Scheduler setup looks good; consider lifetime assumptions of captured referencesThe three scheduled tasks mirror the expected 1s tick plus slower housekeeping and relay pacing, and the
IsValid()gate on the heavier governance maintenance/relay work makes sense.One thing to double‑check:
thisand&connmanare captured by reference in lambdas that may outliveNetGovernanceif shutdown/teardown ordering ever changes. IfScheduleis called once at init andNetGovernance/CConnmanboth live until scheduler shutdown, this is fine; if not, you may want a stop hook or a weak/indirection pattern.
56-61: Governance sync request wiring is straightforward
SendGovernanceSyncRequest’s construction ofMNGOVERNANCESYNCwith an empty Bloom filter and a zero hash matches the expectations inProcessMessageand keeps the wire encoding simple. No issues here.
63-152: Vote request throttling and per‑hash/per‑peer limits look consistentThe logic in
RequestGovernanceObjectVotes(per‑hash peer caps, projected vote count limit per peer,MAX_INV_SZguard, and staticmapAskedRecentlywith a mutex) is coherent and appears to preserve the intended behavior of avoiding bandwidth explosions while still stressing non‑main networks more heavily.Assuming
FetchGovernanceObjectVotesis responsible for aging outmapAskedRecentlyentries based onnNowandnTimeout, this design should remain bounded over long uptimes. If that assumption changed in the refactor, it’s worth confirming to avoid unbounded growth ofmapAskedRecently.
345-449: ProcessMessage refactor preserves structure; minor duplication onlyThe three branches for
MNGOVERNANCESYNC,MNGOVERNANCEOBJECT, andMNGOVERNANCEOBJECTVOTElook like a direct lift from the old governance message handler, with the right hand‑offs toCGovernanceManagerandPeerManagerand appropriate sync gating and misbehavior scoring.There is some duplicated
IsBlockchainSynced()checking (top of function plus inside the object/vote branches), but that’s harmless and may even be desirable given the concurrency between sync and net threads. No changes needed here.src/net_processing.cpp (3)
652-652: NetHandler scheduling hook looks sound
ScheduleHandlerscleanly iteratesm_handlersand delegates tohandler->Schedule(scheduler, m_connman), matching the new interface and keeping scheduling centralized inPeerManagerImpl. No locking is needed as long asm_handlersis configured only during init/shutdown, which matches existingAddExtraHandler/RemoveHandlersusage.Also applies to: 1701-1706
661-661: Locking contract forPeerGetRequestedObjectCountnow matches internal state accessRequiring both
!m_peer_mutexand::cs_mainonPeerGetRequestedObjectCountaligns the wrapper withGetRequestedObjectCountand them_node_states(GUARDED_BY(cs_main)) access. The wrapper’s implementation is a straight passthrough, which is correct given the updated precondition; callers just need to ensure they now holdcs_mainwhen using the peer-facing variant.Also applies to: 1650-1659, 6574-6577
5461-5463: PassingCConnman&into NetHandlers is appropriateUpdating the NetHandler dispatch to
handler->ProcessMessage(pfrom, m_connman, msg_type, vRecv);matches the expanded handler API and keeps all P2P sends/connection operations going through the sharedCConnmaninstance. This is consistent with the refactoring goal of separating network orchestration from handler logic.src/governance/governance.h (1)
367-388: Well-structured API boundary for the network/consensus separation.The new "Used by NetGovernance" section clearly delineates the methods needed by the new
NetGovernancehandler. Lock annotations are consistently applied:
cs_relayfor relay inventory operationscs_storefor governance object/vote storage operationscs_mainappropriately added toProcessObjectfor chain-state accessThe design correctly exposes data-fetching methods (
FetchRelayInventory,FetchGovernanceObjectVotes) and processing entry points (ProcessObject,ProcessVote) that allowNetGovernanceto handle network messaging whileCGovernanceManagerfocuses on consensus logic.
GetMNManager()(line 385) returning a reference without lock annotations is correct sincem_dmnmanis a const member initialized at construction.
| if (gArgs.GetBoolArg("-syncmempool", DEFAULT_SYNC_MEMPOOL)) { | ||
| // Now that the blockchain is synced request the mempool from the connected outbound nodes if possible | ||
| for (auto pNodeTmp : snap.Nodes()) { | ||
| bool fRequestedEarlier = m_netfulfilledman.HasFulfilledRequest(pNodeTmp->addr, | ||
| "mempool-sync"); | ||
| if (!pNodeTmp->IsInboundConn() && !fRequestedEarlier && !pNodeTmp->IsBlockRelayOnly()) { | ||
| m_netfulfilledman.AddFulfilledRequest(pNodeTmp->addr, "mempool-sync"); | ||
| connman.PushMessage(pNodeTmp, msgMaker.Make(NetMsgType::MEMPOOL)); | ||
| LogPrint(BCLog::MNSYNC, /* Continued */ | ||
| "Sync Tick -- nTick %d asset_id %d -- syncing mempool from peer=%d\n", nTick, | ||
| asset_id, pNodeTmp->GetId()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BUG: MEMPOOL sync uses CNetMsgMaker from the wrong peer
In the mempool sync block you send MEMPOOL to pNodeTmp using a CNetMsgMaker constructed from pnode->GetCommonVersion():
CNetMsgMaker msgMaker(pnode->GetCommonVersion());
// ...
for (auto pNodeTmp : snap.Nodes()) {
// ...
connman.PushMessage(pNodeTmp, msgMaker.Make(NetMsgType::MEMPOOL));
}CNetMsgMaker bakes in the per‑peer protocol version; reusing a maker built for one peer when sending to another is incorrect and can lead to mismatched serialization if peers negotiate different versions.
You should construct the message maker using pNodeTmp’s negotiated version instead:
- for (auto pNodeTmp : snap.Nodes()) {
+ for (auto pNodeTmp : snap.Nodes()) {
bool fRequestedEarlier = m_netfulfilledman.HasFulfilledRequest(pNodeTmp->addr,
"mempool-sync");
if (!pNodeTmp->IsInboundConn() && !fRequestedEarlier && !pNodeTmp->IsBlockRelayOnly()) {
m_netfulfilledman.AddFulfilledRequest(pNodeTmp->addr, "mempool-sync");
- connman.PushMessage(pNodeTmp, msgMaker.Make(NetMsgType::MEMPOOL));
+ CNetMsgMaker mempoolMsgMaker(pNodeTmp->GetCommonVersion());
+ connman.PushMessage(pNodeTmp, mempoolMsgMaker.Make(NetMsgType::MEMPOOL));
LogPrint(BCLog::MNSYNC, /* Continued */
"Sync Tick -- nTick %d asset_id %d -- syncing mempool from peer=%d\n", nTick,
asset_id, pNodeTmp->GetId());
}
}This keeps behavior aligned with the rest of the codebase, where messages are always serialized with the destination peer’s own common version.
🤖 Prompt for AI Agents
In src/governance/net_governance.cpp around lines 246-257, the MEMPOOL message
is being created with a CNetMsgMaker built from the wrong peer (pnode) which
bakes in an incorrect protocol version; fix it by constructing the CNetMsgMaker
with the destination peer's negotiated version (pNodeTmp->GetCommonVersion())
when sending inside the loop (i.e. create a msgMaker per pNodeTmp or call
CNetMsgMaker(pNodeTmp->GetCommonVersion()) before connman.PushMessage), so each
MEMPOOL message is serialized using the target peer's common version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't be a real issue because all nodes >= MIN_PEER_PROTO_VERSION should support mempool message but I guess it makes sense to refactor it anyway. Could be done in a separate PR though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@UdjinM6, that makes sense—since all nodes at or above MIN_PEER_PROTO_VERSION support the mempool message, the practical risk is minimal. Keeping this PR focused on the network/consensus separation refactoring is the right call.
If you'd like, I can open a follow-up issue to track this refactoring for a future PR, so it doesn't get lost. Just let me know!
🧠 Learnings used
Learnt from: knst
Repo: dashpay/dash PR: 7008
File: src/masternode/sync.h:17-18
Timestamp: 2025-11-25T10:53:37.523Z
Learning: The file src/masternode/sync.h containing `CMasternodeSync` is misnamed and misplaced—it has nothing to do with "masternode" functionality. It should eventually be renamed to `NodeSyncing` or `NodeSyncStatus` and moved to src/node/sync.h as a future refactoring.
Learnt from: knst
Repo: dashpay/dash PR: 7008
File: src/masternode/sync.h:17-18
Timestamp: 2025-11-25T10:53:37.523Z
Learning: In Dash Core, `DEFAULT_SYNC_MEMPOOL` belongs with node synchronization logic (currently in src/masternode/sync.h) rather than with validation logic in src/validation.h, even though other mempool-related constants are in validation.h. The constant is conceptually tied to sync functionality, not validation.
Learnt from: kwvg
Repo: dashpay/dash PR: 6665
File: src/evo/providertx.h:82-82
Timestamp: 2025-06-06T11:53:09.094Z
Learning: In ProTx serialization code (SERIALIZE_METHODS), version checks should use hardcoded maximum flags (/*is_basic_scheme_active=*/true, /*is_extended_addr=*/true) rather than deployment-based flags. This is because serialization code should be able to deserialize any structurally valid ProTx up to the maximum version the code knows how to handle, regardless of current consensus validity. Validation code, not serialization code, is responsible for checking whether a ProTx version is consensus-valid based on deployment status.
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/llmq/utils.cpp:284-298
Timestamp: 2025-11-04T18:24:27.241Z
Learning: In consensus-critical code (such as quorum formation, block validation, or deployment activation logic), do not suggest changes to the logic itself even if the implementation appears theoretically incorrect or off-by-one. Consensus rules, once deployed on the Dash network, must be preserved exactly to avoid network forks. Refactoring PRs should maintain perfect behavioral equivalence. Only suggest logic changes if explicitly accompanied by a DIP (Dash Improvement Proposal) or if the maintainer indicates the consensus rule needs to be changed with appropriate activation logic.
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/governance/**/*.{cpp,h} : Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/wallet/wallet.cpp:0-0
Timestamp: 2025-07-29T14:33:01.040Z
Learning: In refactoring PRs like #6761, kwvg acknowledges code safety improvements (like null pointer checks and unused parameter warnings) but prefers to defer them to follow-up PRs to maintain focus on the primary refactoring objectives, avoiding scope creep.
| void PeerRelayInvFiltered(const CInv& inv, const uint256& relatedTxHash) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); | ||
| void PeerAskPeersForTransaction(const uint256& txid) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); | ||
| size_t PeerGetRequestedObjectCount(NodeId nodeid) const override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, ::cs_main); | ||
| void PeerPostProcessMessage(MessageProcessingResult&& ret) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PeerPostProcessMessage drops peer context, disabling misbehavior and request cleanup
PeerPostProcessMessage currently forwards to:
void PeerManagerImpl::PeerPostProcessMessage(MessageProcessingResult&& ret)
{
PostProcessMessage(std::move(ret), -1);
}PostProcessMessage uses the node argument to:
- Attribute
m_errorto a specific peer viaMisbehaving(node, ...). - Call
EraseObjectRequest(node, ...)undercs_main.
Passing -1 means any m_error or m_to_erase set by callers of PeerPostProcessMessage will be silently ignored: Misbehaving(-1, ...) and EraseObjectRequest(-1, ...) won’t find a peer/state entry. Only m_transactions, m_inventory, and m_dsq are effective.
If NetHandlers are expected to use PeerPostProcessMessage with a real per-peer MessageProcessingResult (which the name strongly suggests), this will undercut DoS accounting and object-request bookkeeping for those subsystems.
Consider tightening this by threading the actual NodeId through the interface, e.g.:
-void PeerPostProcessMessage(MessageProcessingResult&& ret) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
+void PeerPostProcessMessage(MessageProcessingResult&& ret, NodeId node) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);and
-void PeerManagerImpl::PeerPostProcessMessage(MessageProcessingResult&& ret)
-{
- PostProcessMessage(std::move(ret), -1);
-}
+void PeerManagerImpl::PeerPostProcessMessage(MessageProcessingResult&& ret, NodeId node)
+{
+ PostProcessMessage(std::move(ret), node);
+}with corresponding updates to PeerManagerInternal and NetGovernance (or other) call sites so they pass pfrom.GetId() when there is a peer context, and only use -1 explicitly in the rare cases where there truly is none.
Also applies to: 3587-3604, 6579-6582
🤖 Prompt for AI Agents
In src/net_processing.cpp around line 662 (and similarly at 3587-3604 and
6579-6582), PeerPostProcessMessage currently calls PostProcessMessage with -1
which drops peer context and prevents Misbehaving(...) and
EraseObjectRequest(...) from attributing errors/cleanup to the correct peer;
change the PeerPostProcessMessage signature to accept a NodeId (or int node) and
forward that node to PostProcessMessage instead of -1, update the
PeerManagerInternal and NetGovernance (and any other callers) to pass
pfrom.GetId() when a peer exists (or -1 only when there truly is no peer), and
update the override/declaration sites accordingly so m_error and m_to_erase are
handled against the correct peer state under cs_main.
|
it conflicts with #6992 but conflicts are pretty trivial. Whatever which one will get merged first; 2nd will be rebased on the top. |
|
This pull request has conflicts, please rebase. |
It is used to show this warning:
Transaction index can't be disabled with governance validation enabled. Either start with -disablegovernance command line switch or enable transaction index.
New message is shown in this situation now; behavior is changed by forcing disabling governance:
Warning: You are starting with governance validation disabled.
…de/sync and governance/governance
…d code from governance
…uestOrphanObjects It helps to manage amount of public methods of CGovernanceManager
…relevant code to NetGovernance Please note that circular dependency masternode/sync -> net -> masternode/sync existed for a long time, it's not newly introduced
…dependency governance on net_processing
a5ef0da to
ff49ff9
Compare
ff49ff9 to
4a1fdd9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/governance/net_governance.cpp (1)
154-261: BUG:MEMPOOLusesCNetMsgMakerfrom the wrong peer when syncing mempoolIn the mempool sync block,
msgMakeris constructed once per outerpnode:CNetMsgMaker msgMaker(pnode->GetCommonVersion()); ... for (auto pNodeTmp : snap.Nodes()) { ... connman.PushMessage(pNodeTmp, msgMaker.Make(NetMsgType::MEMPOOL)); }
CNetMsgMakerbakes in the destination peer’s protocol version, so reusing a maker built forpnodewhen sending topNodeTmpis incorrect and can lead to version‑mismatched serialization when peers negotiated different protocol versions.You should construct the message maker from each destination peer’s
GetCommonVersion()inside the inner loop.- for (auto pNodeTmp : snap.Nodes()) { + for (auto pNodeTmp : snap.Nodes()) { bool fRequestedEarlier = m_netfulfilledman.HasFulfilledRequest(pNodeTmp->addr, "mempool-sync"); if (!pNodeTmp->IsInboundConn() && !fRequestedEarlier && !pNodeTmp->IsBlockRelayOnly()) { m_netfulfilledman.AddFulfilledRequest(pNodeTmp->addr, "mempool-sync"); - connman.PushMessage(pNodeTmp, msgMaker.Make(NetMsgType::MEMPOOL)); + CNetMsgMaker mempoolMsgMaker(pNodeTmp->GetCommonVersion()); + connman.PushMessage(pNodeTmp, mempoolMsgMaker.Make(NetMsgType::MEMPOOL)); LogPrint(BCLog::MNSYNC, /* Continued */ "Sync Tick -- nTick %d asset_id %d -- syncing mempool from peer=%d\n", nTick, asset_id, pNodeTmp->GetId()); } }
🧹 Nitpick comments (4)
src/governance/net_governance.cpp (1)
22-54: Governance scheduling viaCScheduleris aligned with new handler modelThe three
scheduleEveryregistrations cleanly separate: (1) 1s sync tick, (2) 5‑minute orphan/cleanup once fully synced, and (3) periodic relay of governance inventory. Usingm_gov_manager.IsValid()to gate the heavier tasks avoids touching uninitialized governance state.If you want to minimize work during shutdown, you could also short‑circuit the second and third lambdas on
ShutdownRequested()similarly to the first.src/governance/governance.cpp (2)
183-231:ProcessObjectcorrectly encapsulates object validation; consider making cs_main requirement explicit
CGovernanceManager::ProcessObject:
- Short‑circuits if the object hash is already known (including erased/postponed).
- Runs
MasternodeRateCheck(with the two‑phase “bypass then force” check) undercs_store.- Validates the object locally with the current MN list and chainstate, deferring immature fee cases into
mapPostponedObjects.- Calls
AddGovernanceObjectInternal(govobj, &peer)on success, which requires both::cs_mainandcs_store.NetGovernance currently calls this under
WITH_LOCK(::cs_main, ...), satisfying the locking precondition. To make this contract obvious and prevent future misuse, it would be good to add anAssertLockHeld(::cs_main);at the top ofProcessObject(or callAddGovernanceObject(...)instead of the internal helper).
960-991: Governance vote fetch API cleanly supports NetGovernance scheduling
FetchGovernanceObjectVotes(...):
- Runs under
cs_store, iteratingmapObjects.- Skips deleted objects and those that already hit the
nPeersPerHashMaxlimit inmapAskedRecently, pruning stale entries first.- Partitions hashes into triggers vs. other objects for prioritized querying.
This matches what
NetGovernance::RequestGovernanceObjectVotesexpects and keeps selection logic local to the governance manager.You may want to document in the header that callers must hold their own mutex protecting
mapAskedRecently(as NetGovernance does withcs_recently), since it is mutated inside this method.src/net_processing.cpp (1)
641-648: Centralized handler scheduling viaScheduleHandlerslooks goodThe new
ScheduleHandlers(CScheduler&)override and its implementation that iteratesm_handlersand callshandler->Schedule(scheduler, m_connman)cleanly wires NetHandlers into the shared scheduler and exposesCConnman&as intended. Sincem_handlersis also mutated without locking inAddExtraHandler/RemoveHandlers, this relies on lifecycle discipline (no concurrent mutation while scheduling); if there’s any chance of runtime additions/removals later, consider documenting that assumption or guardingm_handlerswith a mutex as a future refactor.Also applies to: 1696-1701
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (19)
src/Makefile.am(2 hunks)src/governance/governance.cpp(9 hunks)src/governance/governance.h(1 hunks)src/governance/net_governance.cpp(1 hunks)src/governance/net_governance.h(1 hunks)src/init.cpp(3 hunks)src/instantsend/net_instantsend.cpp(1 hunks)src/instantsend/net_instantsend.h(1 hunks)src/llmq/net_signing.cpp(1 hunks)src/llmq/net_signing.h(1 hunks)src/masternode/sync.cpp(1 hunks)src/masternode/sync.h(2 hunks)src/net_processing.cpp(5 hunks)src/net_processing.h(3 hunks)src/node/chainstate.cpp(0 hunks)src/node/chainstate.h(0 hunks)src/test/util/setup_common.cpp(0 hunks)src/validation.h(0 hunks)test/lint/lint-circular-dependencies.py(1 hunks)
💤 Files with no reviewable changes (4)
- src/test/util/setup_common.cpp
- src/node/chainstate.h
- src/node/chainstate.cpp
- src/validation.h
🚧 Files skipped from review as they are similar to previous changes (2)
- src/governance/net_governance.h
- src/Makefile.am
🧰 Additional context used
📓 Path-based instructions (7)
src/**/*.{cpp,h,hpp,cc}
📄 CodeRabbit inference engine (CLAUDE.md)
Dash Core implementation must be written in C++20, requiring at least Clang 16 or GCC 11.1
Files:
src/instantsend/net_instantsend.hsrc/llmq/net_signing.hsrc/net_processing.hsrc/init.cppsrc/governance/net_governance.cppsrc/llmq/net_signing.cppsrc/masternode/sync.cppsrc/masternode/sync.hsrc/governance/governance.cppsrc/instantsend/net_instantsend.cppsrc/governance/governance.hsrc/net_processing.cpp
src/{masternode,evo,llmq,governance,coinjoin}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Dash-specific database implementations: CFlatDB for persistent storage (MasternodeMetaStore, GovernanceStore, SporkStore, NetFulfilledRequestStore) and CDBWrapper extensions for Evolution/DKG/InstantSend/Quorum/RecoveredSigs data
Files:
src/llmq/net_signing.hsrc/governance/net_governance.cppsrc/llmq/net_signing.cppsrc/masternode/sync.cppsrc/masternode/sync.hsrc/governance/governance.cppsrc/governance/governance.h
src/{masternode,llmq}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
BLS integration must be used for cryptographic foundation of advanced masternode features
Files:
src/llmq/net_signing.hsrc/llmq/net_signing.cppsrc/masternode/sync.cppsrc/masternode/sync.h
src/llmq/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
src/llmq/**/*.{cpp,h}: LLMQ quorums must support multiple configurations (50/60, 400/60, 400/85) for different services (ChainLocks, InstantSend, governance voting)
InstantSend implementation must provide distributed key generation for secure transaction locking with quorum consensus
ChainLocks implementation must prevent reorganizations and provide block finality through 51% attack prevention
Files:
src/llmq/net_signing.hsrc/llmq/net_signing.cpp
src/{masternode,llmq,evo,coinjoin,governance}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Use unordered_lru_cache for efficient caching with LRU eviction in Dash-specific data structures
Files:
src/llmq/net_signing.hsrc/governance/net_governance.cppsrc/llmq/net_signing.cppsrc/masternode/sync.cppsrc/masternode/sync.hsrc/governance/governance.cppsrc/governance/governance.h
src/governance/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
Files:
src/governance/net_governance.cppsrc/governance/governance.cppsrc/governance/governance.h
src/{masternode,evo}/**/*.{cpp,h}
📄 CodeRabbit inference engine (CLAUDE.md)
Masternode lists must use immutable data structures (Immer library) for thread safety
Files:
src/masternode/sync.cppsrc/masternode/sync.h
🧠 Learnings (31)
📓 Common learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/llmq/utils.cpp:284-298
Timestamp: 2025-11-04T18:24:27.241Z
Learning: In consensus-critical code (such as quorum formation, block validation, or deployment activation logic), do not suggest changes to the logic itself even if the implementation appears theoretically incorrect or off-by-one. Consensus rules, once deployed on the Dash network, must be preserved exactly to avoid network forks. Refactoring PRs should maintain perfect behavioral equivalence. Only suggest logic changes if explicitly accompanied by a DIP (Dash Improvement Proposal) or if the maintainer indicates the consensus rule needs to be changed with appropriate activation logic.
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/wallet/wallet.cpp:0-0
Timestamp: 2025-07-29T14:33:01.040Z
Learning: In refactoring PRs like #6761, kwvg acknowledges code safety improvements (like null pointer checks and unused parameter warnings) but prefers to defer them to follow-up PRs to maintain focus on the primary refactoring objectives, avoiding scope creep.
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/governance/**/*.{cpp,h} : Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,consensus,net_processing}/**/*.{cpp,h} : ValidationInterface callbacks must be used for event-driven architecture to coordinate subsystems during block/transaction processing
Applied to files:
src/net_processing.hsrc/init.cppsrc/governance/governance.cppsrc/governance/governance.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/governance/**/*.{cpp,h} : Governance implementation must support governance objects (proposals, triggers, superblock management) and on-chain voting with tallying
Applied to files:
src/init.cppsrc/governance/net_governance.cppsrc/masternode/sync.cppsrc/governance/governance.cppsrc/governance/governance.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/node/chainstate.{cpp,h} : Chainstate initialization must be separated into dedicated src/node/chainstate.* files
Applied to files:
src/init.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/evo/**/*.{cpp,h} : Special transactions use payload serialization routines defined in src/evo/specialtx.h and must include appropriate special transaction types (ProRegTx, ProUpServTx, ProUpRegTx, ProUpRevTx)
Applied to files:
src/init.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/evo/evodb/**/*.{cpp,h} : Evolution Database (CEvoDb) must handle masternode snapshots, quorum state, governance objects with efficient differential updates for masternode lists
Applied to files:
src/init.cppsrc/masternode/sync.cppsrc/masternode/sync.hsrc/governance/governance.cppsrc/governance/governance.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{masternode,evo,llmq,governance,coinjoin}/**/*.{cpp,h} : Use Dash-specific database implementations: CFlatDB for persistent storage (MasternodeMetaStore, GovernanceStore, SporkStore, NetFulfilledRequestStore) and CDBWrapper extensions for Evolution/DKG/InstantSend/Quorum/RecoveredSigs data
Applied to files:
src/init.cppsrc/masternode/sync.hsrc/governance/governance.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/llmq/**/*.{cpp,h} : InstantSend implementation must provide distributed key generation for secure transaction locking with quorum consensus
Applied to files:
src/init.cpp
📚 Learning: 2025-10-28T08:54:00.392Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6926
File: test/functional/feature_governance_cl.py:0-0
Timestamp: 2025-10-28T08:54:00.392Z
Learning: In Dash tests, the scheduler (mockscheduler) operates independently of network state. Isolated nodes should still run scheduler-based cleanup processes like governance cleanup, even if they have different state due to network isolation.
Applied to files:
src/init.cppsrc/governance/governance.cpp
📚 Learning: 2025-11-25T10:53:37.523Z
Learnt from: knst
Repo: dashpay/dash PR: 7008
File: src/masternode/sync.h:17-18
Timestamp: 2025-11-25T10:53:37.523Z
Learning: The file src/masternode/sync.h containing `CMasternodeSync` is misnamed and misplaced—it has nothing to do with "masternode" functionality. It should eventually be renamed to `NodeSyncing` or `NodeSyncStatus` and moved to src/node/sync.h as a future refactoring.
Applied to files:
src/governance/net_governance.cppsrc/masternode/sync.cppsrc/masternode/sync.hsrc/governance/governance.cpp
📚 Learning: 2025-11-25T10:53:37.523Z
Learnt from: knst
Repo: dashpay/dash PR: 7008
File: src/masternode/sync.h:17-18
Timestamp: 2025-11-25T10:53:37.523Z
Learning: In Dash Core, `DEFAULT_SYNC_MEMPOOL` belongs with node synchronization logic (currently in src/masternode/sync.h) rather than with validation logic in src/validation.h, even though other mempool-related constants are in validation.h. The constant is conceptually tied to sync functionality, not validation.
Applied to files:
src/governance/net_governance.cppsrc/masternode/sync.cppsrc/masternode/sync.hsrc/governance/governance.cpp
📚 Learning: 2025-09-09T21:36:58.969Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:223-232
Timestamp: 2025-09-09T21:36:58.969Z
Learning: In RawSender class (src/stats/rawsender.cpp), socket access operations (m_sock and m_server) should be protected by the cs_net mutex, not avoiding synchronization entirely. While lock overhead concerns are valid in general, socket operations require proper synchronization via cs_net.
Applied to files:
src/governance/net_governance.cppsrc/instantsend/net_instantsend.cppsrc/net_processing.cpp
📚 Learning: 2025-06-06T11:53:09.094Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6665
File: src/evo/providertx.h:82-82
Timestamp: 2025-06-06T11:53:09.094Z
Learning: In ProTx serialization code (SERIALIZE_METHODS), version checks should use hardcoded maximum flags (/*is_basic_scheme_active=*/true, /*is_extended_addr=*/true) rather than deployment-based flags. This is because serialization code should be able to deserialize any structurally valid ProTx up to the maximum version the code knows how to handle, regardless of current consensus validity. Validation code, not serialization code, is responsible for checking whether a ProTx version is consensus-valid based on deployment status.
Applied to files:
src/governance/net_governance.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{validation,txmempool}/**/*.{cpp,h} : Block validation and mempool handling must use extensions to Bitcoin Core mechanisms for special transaction validation and enhanced transaction relay
Applied to files:
src/masternode/sync.hsrc/governance/governance.cpp
📚 Learning: 2025-11-04T18:24:27.241Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/llmq/utils.cpp:284-298
Timestamp: 2025-11-04T18:24:27.241Z
Learning: In consensus-critical code (such as quorum formation, block validation, or deployment activation logic), do not suggest changes to the logic itself even if the implementation appears theoretically incorrect or off-by-one. Consensus rules, once deployed on the Dash network, must be preserved exactly to avoid network forks. Refactoring PRs should maintain perfect behavioral equivalence. Only suggest logic changes if explicitly accompanied by a DIP (Dash Improvement Proposal) or if the maintainer indicates the consensus rule needs to be changed with appropriate activation logic.
Applied to files:
src/masternode/sync.hsrc/net_processing.cpp
📚 Learning: 2025-06-09T16:43:20.996Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
Applied to files:
src/masternode/sync.hsrc/net_processing.cpp
📚 Learning: 2025-10-05T20:38:28.457Z
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.
Applied to files:
src/masternode/sync.h
📚 Learning: 2025-07-29T14:32:48.369Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.
Applied to files:
src/masternode/sync.hsrc/net_processing.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{masternode,llmq,evo,coinjoin,governance}/**/*.{cpp,h} : Use unordered_lru_cache for efficient caching with LRU eviction in Dash-specific data structures
Applied to files:
src/masternode/sync.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{masternode,llmq}/**/*.{cpp,h} : BLS integration must be used for cryptographic foundation of advanced masternode features
Applied to files:
src/masternode/sync.hsrc/governance/governance.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/coinjoin/**/*.{cpp,h} : CoinJoin implementation must use masternode-coordinated mixing sessions with uniform denomination outputs
Applied to files:
src/masternode/sync.h
📚 Learning: 2025-11-04T18:23:28.175Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/governance/classes.cpp:147-154
Timestamp: 2025-11-04T18:23:28.175Z
Learning: In src/governance/classes.cpp, CSuperblock::GetPaymentsLimit intentionally uses synthetic difficulty constants (nBits = 1 for mainnet, powLimit for networks with min difficulty) and simple height-based V20 activation checks instead of actual chain block data. This is by design because superblocks themselves are "synthetic" governance payment blocks, not regular mined blocks.
Applied to files:
src/masternode/sync.hsrc/governance/governance.h
📚 Learning: 2025-10-21T11:09:34.688Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6849
File: src/governance/governance.cpp:1339-1343
Timestamp: 2025-10-21T11:09:34.688Z
Learning: In PR #6849, `cmapVoteToObject` was intentionally moved from `GovernanceStore` to `CGovernanceManager` as a memory-only variable and is NOT guarded by `cs_store`. It relies on `CacheMap`'s internal thread-safety instead.
Applied to files:
src/governance/governance.cppsrc/governance/governance.h
📚 Learning: 2025-09-09T21:36:58.969Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:223-232
Timestamp: 2025-09-09T21:36:58.969Z
Learning: In RawSender class (src/stats/rawsender.cpp), socket operations are properly synchronized using the cs_net mutex. The m_sock and m_server members are GUARDED_BY(cs_net), and methods like Connect(), SendDirectly(), and ReconnectThread() use appropriate locking with cs_net to prevent race conditions on socket access.
Applied to files:
src/instantsend/net_instantsend.cpp
📚 Learning: 2025-09-09T21:36:31.504Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:31.504Z
Learning: In RawSender class (src/stats/rawsender.cpp), m_sock access requires synchronization using the cs_net mutex. The race condition exists between SendDirectly() (callable from any thread) and Connect() (called by ReconnectThread), where both read and write m_sock concurrently. The cs_net mutex properly coordinates these network operations.
Applied to files:
src/instantsend/net_instantsend.cpp
📚 Learning: 2025-09-09T21:36:11.833Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:11.833Z
Learning: In RawSender class (src/stats/rawsender.cpp), cs_net is the appropriate mutex for protecting socket access (m_sock) and network operations, not additional custom locks. The implementation correctly uses cs_net with GUARDED_BY annotations and EXCLUSIVE_LOCKS_REQUIRED to synchronize socket access between SendDirectly() and ReconnectThread().
Applied to files:
src/instantsend/net_instantsend.cppsrc/governance/governance.hsrc/net_processing.cpp
📚 Learning: 2025-09-09T21:36:31.504Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:31.504Z
Learning: In RawSender class (src/stats/rawsender.cpp), m_sock access is protected by the cs_net mutex. This mutex coordinates between the TCP send path in SendDirectly() and the reconnection operations in Connect()/Reconnect() methods, ensuring proper synchronization of socket state.
Applied to files:
src/instantsend/net_instantsend.cpp
📚 Learning: 2025-09-09T21:36:11.833Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6837
File: src/stats/rawsender.cpp:0-0
Timestamp: 2025-09-09T21:36:11.833Z
Learning: In RawSender class (src/stats/rawsender.cpp), cs_net is the appropriate mutex for protecting socket access (m_sock) and network operations, not additional custom locks.
Applied to files:
src/instantsend/net_instantsend.cpp
📚 Learning: 2025-11-13T20:02:55.480Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6969
File: src/evo/deterministicmns.h:441-479
Timestamp: 2025-11-13T20:02:55.480Z
Learning: In `src/evo/deterministicmns.h`, the `internalId` field in `CDeterministicMN` and the `mnInternalIdMap` in `CDeterministicMNList` are non-deterministic and used only for internal bookkeeping and efficient lookups. Different nodes can assign different internalIds to the same masternode depending on their sync history. Methods like `IsEqual()` intentionally ignore internalId mappings and only compare consensus-critical deterministic fields (proTxHash, collateral, state, etc.).
Applied to files:
src/governance/governance.h
📚 Learning: 2025-08-19T14:57:31.801Z
Learnt from: knst
Repo: dashpay/dash PR: 6692
File: src/llmq/blockprocessor.cpp:217-224
Timestamp: 2025-08-19T14:57:31.801Z
Learning: In PR #6692, knst acknowledged a null pointer dereference issue in ProcessBlock() method where LookupBlockIndex may return nullptr but is passed to gsl::not_null, and created follow-up PR #6789 to address it, consistent with avoiding scope creep in performance-focused PRs.
Applied to files:
src/net_processing.cpp
📚 Learning: 2025-07-29T14:33:01.040Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/wallet/wallet.cpp:0-0
Timestamp: 2025-07-29T14:33:01.040Z
Learning: In refactoring PRs like #6761, kwvg acknowledges code safety improvements (like null pointer checks and unused parameter warnings) but prefers to defer them to follow-up PRs to maintain focus on the primary refactoring objectives, avoiding scope creep.
Applied to files:
src/net_processing.cpp
🧬 Code graph analysis (7)
src/instantsend/net_instantsend.h (2)
src/instantsend/net_instantsend.cpp (2)
ProcessMessage(17-65)ProcessMessage(17-17)src/llmq/net_signing.cpp (2)
ProcessMessage(19-35)ProcessMessage(19-19)
src/llmq/net_signing.h (2)
src/net_processing.cpp (12)
ProcessMessage(3687-5477)ProcessMessage(3687-3692)pfrom(613-613)pfrom(634-635)pfrom(748-750)pfrom(759-759)pfrom(767-767)pfrom(770-770)pfrom(772-772)pfrom(774-774)pfrom(870-870)pfrom(1052-1052)src/llmq/net_signing.cpp (2)
ProcessMessage(19-35)ProcessMessage(19-19)
src/net_processing.h (1)
src/net_processing.cpp (20)
PeerGetRequestedObjectCount(6580-6583)PeerGetRequestedObjectCount(6580-6580)nodeid(623-623)nodeid(626-626)nodeid(639-639)nodeid(651-651)nodeid(656-656)nodeid(674-674)nodeid(676-676)nodeid(714-715)nodeid(725-725)nodeid(857-857)nodeid(859-859)nodeid(1035-1035)nodeid(1070-1070)scheduler(619-619)scheduler(647-647)scheduler(689-689)ScheduleHandlers(1696-1701)ScheduleHandlers(1696-1696)
src/governance/net_governance.cpp (2)
src/net_processing.cpp (3)
scheduler(619-619)scheduler(647-647)scheduler(689-689)src/net.h (1)
FullyConnectedOnly(1296-1296)
src/masternode/sync.h (1)
src/masternode/sync.cpp (6)
BumpAssetLastTime(43-48)BumpAssetLastTime(43-43)GetAssetName(50-59)GetAssetName(50-50)GetSyncStatus(89-97)GetSyncStatus(89-89)
src/instantsend/net_instantsend.cpp (2)
src/net_processing.cpp (12)
ProcessMessage(3687-5477)ProcessMessage(3687-3692)pfrom(613-613)pfrom(634-635)pfrom(748-750)pfrom(759-759)pfrom(767-767)pfrom(770-770)pfrom(772-772)pfrom(774-774)pfrom(870-870)pfrom(1052-1052)src/llmq/net_signing.cpp (2)
ProcessMessage(19-35)ProcessMessage(19-19)
src/governance/governance.h (2)
src/governance/governance.cpp (22)
FetchRelayInventory(449-455)FetchRelayInventory(449-449)CheckAndRemove(332-447)CheckAndRemove(332-332)RequestOrphanObjects(1169-1208)RequestOrphanObjects(1169-1169)FetchGovernanceObjectVotes(962-991)FetchGovernanceObjectVotes(962-963)RequestGovernanceObject(928-958)RequestGovernanceObject(928-928)SyncObjects(650-692)SyncObjects(650-650)SyncSingleObjVotes(597-648)SyncSingleObjVotes(597-597)AcceptMessage(993-1005)AcceptMessage(993-993)ProcessObject(183-231)ProcessObject(183-183)GetMNManager(960-960)GetMNManager(960-960)ProcessVote(800-858)ProcessVote(800-800)src/governance/object.cpp (2)
ProcessVote(58-159)ProcessVote(58-59)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
- GitHub Check: linux64_multiprocess-build / Build source
- GitHub Check: linux64_tsan-build / Build source
- GitHub Check: arm-linux-build / Build source
- GitHub Check: mac-build / Build source
- GitHub Check: win64-build / Build source
- GitHub Check: linux64_ubsan-build / Build source
- GitHub Check: linux64_sqlite-build / Build source
- GitHub Check: linux64-build / Build source
- GitHub Check: linux64_fuzz-build / Build source
- GitHub Check: linux64_nowallet-build / Build source
🔇 Additional comments (25)
src/llmq/net_signing.cpp (1)
19-19: LGTM: ProcessMessage signature updated for API consistency.The added
CConnman¶meter aligns with the broader NetHandler interface harmonization across the codebase. The parameter is currently unused but available for future networking needs.src/llmq/net_signing.h (1)
28-28: LGTM: Declaration matches implementation.The signature update correctly reflects the implementation change in the corresponding .cpp file.
src/masternode/sync.h (1)
67-73: LGTM: New accessors support governance refactoring.The added public methods (
BumpAttempt(),GetLastBump(),IsReachedBestHeader()) appropriately expose internal sync state needed by the governance network handler, aligning with the PR's goal of separating network and consensus logic.src/governance/governance.h (1)
367-387: LGTM: Well-structured governance interface for network separation.The new public API surface clearly delineates methods used by NetGovernance, with comprehensive locking annotations (
EXCLUSIVE_LOCKS_REQUIRED) that document synchronization requirements. This reorganization successfully separates network-facing operations from internal governance logic, advancing the PR's refactoring goals.src/instantsend/net_instantsend.cpp (1)
17-17: LGTM: Consistent signature update across NetHandler implementations.The CConnman& parameter addition aligns with the NetHandler interface standardization. While currently unused, it maintains API consistency and enables future networking functionality.
src/instantsend/net_instantsend.h (1)
34-34: LGTM: Declaration consistent with implementation.The signature update correctly reflects the corresponding .cpp implementation and NetHandler interface requirements.
test/lint/lint-circular-dependencies.py (1)
51-51: LGTM: Simplified circular dependency structure.The consolidation of multiple governance-related circular dependencies into a single
masternode/sync -> net -> masternode/syncpath demonstrates successful architectural improvement. This simpler dependency graph validates the refactoring's goal of better separation between network and consensus logic.src/net_processing.h (3)
67-67: LGTM: New method supports handler decision-making.The
PeerGetRequestedObjectCount()method appropriately exposes per-peer request state, enabling NetGovernance and other handlers to make informed sync decisions based on peer activity.
83-84: LGTM: Handler interface enhancements enable unified scheduling.The addition of
Schedule()and the updatedProcessMessage()signature establish a consistent pattern for handlers to register periodic tasks and access connection management. This standardization supports the modular handler architecture introduced in this refactoring.
174-174: LGTM: Central scheduling coordination point.The
ScheduleHandlers()method provides a clean entry point for initializing all registered handlers' scheduled tasks, maintaining architectural consistency across the handler subsystem.src/masternode/sync.cpp (1)
7-8: Includes correctly narrowed to chain/net types actually usedAdding
chain.handnet.hmatches theCBlockIndexandCNode/CConnmanusages in this file and helps decouple from higher-level headers. No behavior change here.src/init.cpp (3)
90-92: Governance net include and-syncmempoolwiring look consistentIncluding
governance/net_governance.hhere and usingDEFAULT_SYNC_MEMPOOLfor the-syncmempooloption keeps init’s dependency surface minimal while placing the mempool-sync default next to node-syncing logic (inmasternode/sync.h). No issues from a wiring/ownership standpoint.Also applies to: 578-578
1979-2031: UpdatedLoadChainstatecall matches the new consensus/node wiringThe new
LoadChainstate(...)invocation passesCGovernanceManager, masternode meta, sync, spork, evo, and mempool objects without the oldis_governance_enabled/-txindex/NetworkIDString()parameters. Givenis_governance_enabledstill only gatesgovman->LoadCache(...), this preserves behavior while simplifying the chainstate API surface.
2233-2234: NetGovernance handler integration into PeerManager/scheduler is coherent
NetGovernanceis added as an extra handler, then all handlers are scheduled viapeerman->ScheduleHandlers(*node.scheduler)and later started withpeerman->StartScheduledTasks(*node.scheduler). This keeps governance networking aligned with the generic handler scheduling model and respects object lifetimes (handlers scheduled before RPC warmup ends, scheduler stopped beforepeerman/govmanare reset).Also applies to: 2302-2306, 2680-2681
src/governance/net_governance.cpp (4)
56-61: Governance sync request helper correctly encapsulates per‑peer versioning
SendGovernanceSyncRequestreuses the legacy pattern of sendingMNGOVERNANCESYNCwith an empty filter, and crucially buildsCNetMsgMakerfrompnode->GetCommonVersion(), so serialization matches the target peer.
63-152: Vote request scheduling with per‑hash/per‑peer caps looks sound
RequestGovernanceObjectVotes:
- Uses distinct caps for real networks vs. regtest (
REALNET_PEERS_PER_HASH/REGTEST_PEERS_PER_HASH).- Computes
nMaxObjRequestsPerNodebased on projected votes and current MN count to stress non‑mainnet.- Maintains
mapAskedRecentlyunder a dedicated mutex and prunes expired entries.- Avoids
MAX_INV_SZoverflow by consultingPeerGetRequestedObjectCountundercs_main.- Skips non‑relay and inbound MN connections.
This mirrors the previous logic while cleanly separating it into a handler‑local API.
265-343: Governance sync tick logic preserves the original asset‑transition behaviorThe governance phase of
ProcessTick:
- Skips governance entirely if
m_gov_manager.IsValid()is false, moving straight toMASTERNODE_SYNC_FINISHED.- Enforces
MASTERNODE_SYNC_TIMEOUT_SECONDSwith the existing logging and fallback behavior.- Marks each peer with
"governance-sync"only once and then sends a sync request viaSendGovernanceSyncRequest.- After all peers are marked, performs per‑peer per‑object vote requests via
RequestGovernanceObjectVotesand uses the historicnTimeNoObjectsLeft/nLastVotesheuristic to decide when governance sync is complete.This matches prior semantics while routing all network IO through
NetGovernance.
345-449: Message dispatch cleanly separated into NetGovernance/CGovernanceManager layers
ProcessMessage:
- Immediately bails out if governance is disabled (
!m_gov_manager.IsValid()) or the blockchain is not yet synced.- For
MNGOVERNANCESYNC, defers toCGovernanceManager::SyncObjects/SyncSingleObjVotesand usesPeerPostProcessMessageto send the resulting inventories plus aSYNCSTATUSCOUNT.- For
MNGOVERNANCEOBJECT, erases the outstanding request undercs_main, then callsCGovernanceManager::ProcessObjectunderWITH_LOCK(cs_main, ...), satisfying its need forcs_main/cs_storeand applying a ban score on hard failure.- For
MNGOVERNANCEOBJECTVOTE, erases the outstanding request, checks sync, logs with the tip MN list, enforcesAcceptMessage, and then callsProcessVote; on success it bumps the sync timer and relays only if fully synced.Threading and ownership expectations line up with the new governance APIs.
src/governance/governance.cpp (5)
27-27: Switch tovalidationinterface.hkeeps governance decoupled from validation internalsIncluding
validationinterface.hinstead ofvalidation.his appropriate here: this file only needs the notification interface (GetMainSignals()), not the full validation machinery, which helps reduce coupling.
449-455: Relay inventory fetch/clear undercs_relayis straightforward
FetchRelayInventory()swapsm_relay_invsinto a local vector undercs_relay, providing a cheap, race‑free way for NetGovernance to drain pending relay items. This is a clean separation of producer (RelayObject/RelayVote) and consumer (NetGovernance::Schedule).
597-692: Addingcs_storelocking to sync helpers tightens thread safetyBoth
SyncSingleObjVotesandSyncObjectsnow:
- Lock
cs_storewhile walkingmapObjectsand accessing per‑object vote files.- Still gate on
m_mn_sync.IsSynced()and onm_netfulfilledmanlimits for full sync requests.- Use
CNetMsgMaker(peer.GetCommonVersion())to sendSYNCSTATUSCOUNTwith accurate per‑peer counts.This improves consistency with other
CGovernanceManagermethods and avoids concurrent map access races.
1173-1208: Orphan vote cleanup before requesting parents is sensible and bounded
RequestOrphanObjectsnow:
- Computes
nNowin seconds and removes stalecmmapOrphanVotesentries whose stored expiry time is in the past.- Then builds
vecHashesFilteredonly for hashes not already inmapObjects.- Uses
CConnman::NodesSnapshotwithFullyConnectedOnlyand only sends requests to peers that can relay.This avoids repeatedly requesting already‑expired orphan parents and keeps the orphan map bounded over time.
960-960:GetMNManageraccessor exposes deterministic MN manager for net layer
GetMNManager()returning*Assert(m_dmnman)is the right minimal API for NetGovernance to get the current deterministic MN list without exposing broader CGovernanceManager internals.src/net_processing.cpp (2)
5467-5469: PassingCConnman&into NetHandlers’ProcessMessageis consistent with the new APIUpdating the dispatch loop to call
handler->ProcessMessage(pfrom, m_connman, msg_type, vRecv)gives NetHandlers direct access to the connection manager and matches the refactored NetHandler interface, without changing control flow here. No additional issues from this change inProcessMessageare apparent.
649-657:PeerGetRequestedObjectCountlock contract now matchesGetRequestedObjectCountAnnotating
PeerGetRequestedObjectCountwithEXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, ::cs_main)ensures the wrapper's precondition aligns with its callee. SinceGetRequestedObjectCountaccessesm_node_states(which isGUARDED_BY(cs_main)), callers must holdcs_main. Verify that all call sites ofPeerGetRequestedObjectCountholdcs_mainand respect the!m_peer_mutexordering to prevent hitting the internalAssertLockHeld(cs_main)or racing onm_node_states.
fixed |
| return int(vTriggerObjHashes.size() + vOtherObjHashes.size()); | ||
| } | ||
|
|
||
| void NetGovernance::ProcessTick(CConnman& connman) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function does more than just governance sync, I don't think it's the right place for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider smth like 491f769
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function does more than just governance sync, I don't think it's the right place for it.
Yes, I would agree that it's not the best name and place, but the previous caller has been CMasternodeSync::DoMaintenance; it has nothing to do with maintenance as well.
Also Governance should be aware if node is synced (IsBlockchainSynced, IsSynced), but this object CMasternodeSync also do a lot of calls from CGovernanceManager;
Probably better from "architecture" and logical point of view, create one more class and move CMasternodeSync's scheduler to there, but every new file -> bigger compilation time, so, each new file with non-trivial logic is an extra burden to support and to compile.
Should I still change it or that's non-actionable comment? @UdjinM6
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
working on, PR converted to draft
| if (gArgs.GetBoolArg("-syncmempool", DEFAULT_SYNC_MEMPOOL)) { | ||
| // Now that the blockchain is synced request the mempool from the connected outbound nodes if possible | ||
| for (auto pNodeTmp : snap.Nodes()) { | ||
| bool fRequestedEarlier = m_netfulfilledman.HasFulfilledRequest(pNodeTmp->addr, | ||
| "mempool-sync"); | ||
| if (!pNodeTmp->IsInboundConn() && !fRequestedEarlier && !pNodeTmp->IsBlockRelayOnly()) { | ||
| m_netfulfilledman.AddFulfilledRequest(pNodeTmp->addr, "mempool-sync"); | ||
| connman.PushMessage(pNodeTmp, msgMaker.Make(NetMsgType::MEMPOOL)); | ||
| LogPrint(BCLog::MNSYNC, /* Continued */ | ||
| "Sync Tick -- nTick %d asset_id %d -- syncing mempool from peer=%d\n", nTick, | ||
| asset_id, pNodeTmp->GetId()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't be a real issue because all nodes >= MIN_PEER_PROTO_VERSION should support mempool message but I guess it makes sense to refactor it anyway. Could be done in a separate PR though.
… coordinator pattern Problem: PR dashpay#7008 moved ProcessTick to NetGovernance, but ProcessTick handles more than just governance synchronization - it also handles spork sync, blockchain sync, and mempool sync. This creates a naming mismatch where "NetGovernance" contains non-governance code. Solution: Implement coordinator pattern to properly separate concerns: 1. **SyncPhaseHandlerInterface** (sync_phase_handler.h) - Defines common interface for all sync phase handlers - ProcessPeer(): called for each peer during sync - PostPeerLoop(): called after processing all peers - OnSyncComplete(): called when phase completes 2. **NetNodeSyncCoordinator** (masternode/net_sync.{h,cpp}) - Manages sync state machine - Delegates to phase-specific handlers - Supports always-active handlers (run during all phases) - Replaces monolithic ProcessTick logic 3. **NetSporkHandler** (spork/net_spork.{h,cpp}) - Handles ONLY spork synchronization - Runs as always-active handler during all sync phases - ~8 lines of focused code 4. **NetBlockchainSyncHandler** (masternode/net_blockchain_sync.{h,cpp}) - Handles ONLY blockchain + mempool synchronization - Runs during MASTERNODE_SYNC_BLOCKCHAIN phase - ~30 lines of focused code 5. **NetGovernance** (governance/net_governance.{h,cpp}) - refactored - Now handles ONLY governance synchronization - Implements SyncPhaseHandlerInterface for MASTERNODE_SYNC_GOVERNANCE phase - Removed spork, blockchain, and mempool sync code (~50 lines removed) - Maintains ProcessMessage for governance network messages - PostPeerLoop requests votes on per-object basis and detects completion Benefits: - Single Responsibility: Each handler has one clear purpose - No Naming Mismatch: NetGovernance now only handles governance - Better Testability: Handlers can be tested independently - Cleaner Separation: Sporks, blockchain, and governance properly isolated - Extensibility: Easy to add new sync phases 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Issue being fixed or feature implemented
Separation of consensus & chain code and network & node in Dash Core is blocked by tight connection of network and consensus code; in components such as
llmq::CSigningManager,llmq::CSigSharesManager,coinjoin::client,coinjoin::server,governance/,llmq::CInstantSendManager, etc.It blocks backport's of bitcoin related to 'kernel' project.
What was done?
This PR addresses a dependency of
CGovernanceManageronPeerManagerIt is a split from proof-of-concept PR #6934
Prior work: #6959 #6992
How Has This Been Tested?
Run unit & functional tests.
Run a linter
test/lint/lint-circular-dependencies.pyOverall conception is tested in #6934 as potentially successful to finish separation of network & consensus code.
Breaking Changes
N/A
Checklist: