Skip to content

Conversation

@PastaPastaPasta
Copy link
Member

Issue being fixed or feature implemented

I keep reading CSigSharesManager::CreateSigShare looking for optimizations, and keep getting distracted by single member logic; let's move it into it's own function

What was done?

How Has This Been Tested?

Builds

Breaking Changes

Checklist:

Go over all the following points, and put an x in all the boxes that apply.

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

@PastaPastaPasta PastaPastaPasta added this to the 23.1 milestone Nov 21, 2025
@github-actions
Copy link

github-actions bot commented Nov 21, 2025

⚠️ Potential Merge Conflicts Detected

This PR has potential conflicts with the following open PRs:

Please coordinate with the authors of these PRs to avoid merge conflicts.

@coderabbitai
Copy link

coderabbitai bot commented Nov 21, 2025

Walkthrough

This change extracts single-member quorum handling into a new private method CreateSigShareForSingleMember on CSigSharesManager. CreateSigShare now delegates single-member cases to this method. The new method finds the member index, constructs a CSigShare, signs it with the operator key, validates the signature, updates the share's key on success, logs outcomes, and returns the share wrapped in std::optional. Multi-member signing behavior remains on the original path.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Caller
    participant CSigSharesManager
    participant Quorum
    participant KeyStore
    participant Crypto

    Caller->>CSigSharesManager: CreateSigShare(quorum, id, msgHash)
    alt quorum has single member
        CSigSharesManager->>CSigSharesManager: CreateSigShareForSingleMember(quorum, id, msgHash)
        CSigSharesManager->>Quorum: determineMemberIndex(msgHash)
        Quorum-->>CSigSharesManager: memberIndex
        CSigSharesManager->>CSigSharesManager: construct CSigShare(memberIndex, id, msgHash)
        CSigSharesManager->>KeyStore: getOperatorKey()
        KeyStore-->>CSigSharesManager: operatorKey
        CSigSharesManager->>Crypto: sign(operatorKey, sigShareData)
        Crypto-->>CSigSharesManager: signature
        CSigSharesManager->>Crypto: verify(signature, publicKey, sigShareData)
        Crypto-->>CSigSharesManager: verificationResult
        alt verificationResult == valid
            CSigSharesManager->>CSigSharesManager: update share key, log success
            CSigSharesManager-->>Caller: optional<CSigShare> (value)
        else verificationResult == invalid
            CSigSharesManager->>CSigSharesManager: log failure
            CSigSharesManager-->>Caller: optional<CSigShare> (nullopt)
        end
    else quorum has multiple members
        CSigSharesManager->>CSigSharesManager: existing multi-member signing flow (unchanged)
        CSigSharesManager-->>Caller: optional<CSigShare> (value/nullopt)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Files to review closely:
    • src/llmq/signing_shares.cpp — new method implementation, signing and verification logic, logging and timing
    • src/llmq/signing_shares.h — declaration of the new private helper
  • Pay special attention to:
    • Correct member index determination for single-member quorums
    • Cryptographic signing and verification steps and error handling
    • Any changes in logging/timing that affect observability or performance measurements

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: refactoring to segregate single-member handling into its own function, which aligns perfectly with the code changes and PR intent.
Description check ✅ Passed The description explains the rationale for the change and mentions that single-member logic is being moved to its own function, which directly relates to the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f83a135 and b216446.

📒 Files selected for processing (1)
  • src/llmq/signing_shares.cpp (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 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.
📚 Learning: 2025-08-19T15:08:00.835Z
Learnt from: knst
Repo: dashpay/dash PR: 6692
File: src/llmq/commitment.cpp:54-60
Timestamp: 2025-08-19T15:08:00.835Z
Learning: In Dash Core, llmq_params.size == 1 is used only for regtest environments, not on public networks, which significantly reduces the risk profile of code paths specific to single-member quorums.

Applied to files:

  • src/llmq/signing_shares.cpp
📚 Learning: 2025-07-15T14:53:04.819Z
Learnt from: knst
Repo: dashpay/dash PR: 6691
File: src/test/llmq_params_tests.cpp:148-151
Timestamp: 2025-07-15T14:53:04.819Z
Learning: In the Dash Core LLMQ implementation, signingActiveQuorumCount is never 0 in the actual parameters defined in params.h, making division by zero scenarios unrealistic in the max_cycles() function.

Applied to files:

  • src/llmq/signing_shares.cpp
🪛 GitHub Actions: Clang Diff Format Check
src/llmq/signing_shares.cpp

[error] 1-1: Clang format differences found in source file. Apply formatting changes (lint: clang-format).

⏰ 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). (8)
  • GitHub Check: predict_conflicts
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: x86_64-w64-mingw32 / Build depends
  • GitHub Check: Lint / Run linters
  • GitHub Check: x86_64-apple-darwin / 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 (3)
src/llmq/signing_shares.cpp (3)

1648-1683: Single-member helper extraction looks correct and behavior-preserving

The new CreateSigShareForSingleMember keeps the existing semantics: same member index resolution, sign hash construction via buildSignHash(), operator-key signing via m_mn_activeman.Sign, validity check, UpdateKey() call, and logging. Given this path only applies to is_single_member() quorums (regtest-only per earlier LLMQ params discussions), the risk of this refactor is low and the helper nicely isolates the special case.


1685-1696: Wrapper flow for single vs multi-member quorums looks sound

CreateSigShare now (1) validates membership via IsValidMember, (2) routes single-member quorums through CreateSigShareForSingleMember, and (3) only starts the timing cxxtimer::Timer for the multi-member path. This keeps the multi-member behavior unchanged while avoiding duplicate timers for single-member quorums and centralizing the special-case logic.


1648-1683: Fix clang-format diff to satisfy CI

CI reports a clang-format diff for this file. Please run the project’s clang-format tooling over src/llmq/signing_shares.cpp (or at least the modified region around CreateSigShareForSingleMember / CreateSigShare) and commit the resulting formatting changes so the lint job passes.

Also applies to: 1685-1696

⛔ Skipped due to learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6529
File: src/rpc/governance.cpp:1074-1089
Timestamp: 2025-02-14T15:15:58.165Z
Learning: Code blocks marked with `// clang-format off` and `// clang-format on` directives should be excluded from clang-format suggestions as they are intentionally formatted manually for better readability.

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a 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 (1)
src/llmq/signing_shares.cpp (1)

1685-1726: LGTM! Delegation to single-member handler is correct.

The refactoring successfully separates the single-member logic while preserving the existing multi-member implementation. The validation check (IsValidMember) appropriately occurs before delegation.

Optional: Minor efficiency improvement.

For the single-member path, both activeMasterNodeProTxHash (line 1688) and the timer (line 1687) are retrieved in this function but then retrieved again inside CreateSigShareForSingleMember. Consider moving the single-member check earlier to avoid this duplication:

 std::optional<CSigShare> CSigSharesManager::CreateSigShare(const CQuorum& quorum, const uint256& id, const uint256& msgHash) const
 {
-    cxxtimer::Timer t(true);
-    auto activeMasterNodeProTxHash = m_mn_activeman.GetProTxHash();
-
-    if (!quorum.IsValidMember(activeMasterNodeProTxHash)) {
+    if (!quorum.IsValidMember(m_mn_activeman.GetProTxHash())) {
         return std::nullopt;
     }
 
     if (quorum.params.is_single_member()) {
         return CreateSigShareForSingleMember(quorum, id, msgHash);
     }
+    
+    cxxtimer::Timer t(true);
+    auto activeMasterNodeProTxHash = m_mn_activeman.GetProTxHash();

However, this is a minor optimization and can be deferred, especially given this is a focused refactoring PR.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c9faf42 and f83a135.

📒 Files selected for processing (2)
  • src/llmq/signing_shares.cpp (1 hunks)
  • src/llmq/signing_shares.h (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 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.
🧬 Code graph analysis (1)
src/llmq/signing_shares.h (1)
src/llmq/signing_shares.cpp (2)
  • CreateSigShareForSingleMember (1648-1683)
  • CreateSigShareForSingleMember (1648-1648)
🔇 Additional comments (2)
src/llmq/signing_shares.h (1)

455-456: LGTM! Clean refactoring to separate single-member logic.

The new private helper declaration is well-structured and clearly communicates its purpose. The signature is consistent with the existing CreateSigShare method, and the const-correctness is properly maintained.

src/llmq/signing_shares.cpp (1)

1648-1683: LGTM! Single-member logic successfully extracted.

The implementation correctly handles single-member quorum signature creation with appropriate error handling and logging. The TODO comment about using the QUORUM key instead of the OPERATOR key is preserved, maintaining awareness of the future improvement.

Co-authored-by: Konstantin Akimov <[email protected]>
Copy link
Collaborator

@knst knst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK b216446

Copy link

@UdjinM6 UdjinM6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK b216446

@PastaPastaPasta PastaPastaPasta merged commit 701e05b into dashpay:develop Nov 24, 2025
32 of 37 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants