Skip to content

Conversation

PastaPastaPasta
Copy link
Member

@PastaPastaPasta PastaPastaPasta commented Oct 21, 2025

Issue being fixed or feature implemented

Using std::move here should save on the magnitude of ~10-150 ns depending on how contended the underlying shared_ptr is. This move becomes basically free, with no atomics etc being touched. Currently, we pass a const ref in, then copy it, resulting in 2 unneeded atomic operations (++ for the copy, -- for the destroy of the one we could've just moved in.

What was done?

use std::move

Also; prefer just using the reference to CQuorum where possible, as opposed to the shared_ptr

How Has This Been Tested?

compiles

Breaking Changes

Please describe any breaking changes your code introduces

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)

@github-actions
Copy link

github-actions bot commented Oct 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 Oct 21, 2025

Walkthrough

The PR changes quorum ownership and access semantics across llmq modules: many APIs that previously accepted CQuorumCPtr (pointer) now take CQuorum or CQuorumCPtr by value/non-const, and several call sites move quorum objects into async/thread lambdas. Implementations and callers were updated from pointer syntax (quorum->...) to direct member access (quorum.... or quorum.qc...). Key signature changes occur in signing_shares (AsyncSign, TryRecoverSig, SelectMemberForRecovery, CreateSigShare, ForceReAnnouncement) and quorums (RequestQuorumData, GetQuorumRecoveryStartOffset, StartCachePopulatorThread, StartQuorumDataRecoveryThread). RPC helpers and a local lambda in signing.cpp were adjusted to use movable quorum objects and std::move where appropriate.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

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 "refactor: optimize AsyncSign by using std::move for quorum parameter" accurately describes the primary optimization goal in the changeset. AsyncSign's parameter type has been changed from const CQuorumCPtr& (by-reference) to CQuorumCPtr (by-value) to enable move semantics with std::move, which aligns precisely with what the title states. The title is concise, clear, and specific about the main change. While the PR also includes broader refactoring of other functions to use references instead of pointers (TryRecoverSig, SelectMemberForRecovery, CreateSigShare, ForceReAnnouncement, RequestQuorumData, and others), these are secondary objectives to the primary AsyncSign optimization that the title captures.
Description Check ✅ Passed The pull request description is directly related to the changeset. It explains the performance issue (unnecessary atomic increment/decrement operations on shared_ptr, costing ~10-150 ns), identifies the solution (use std::move and prefer references to CQuorum instead of shared_ptr), and notes that the code compiles. The description accurately reflects what the changes accomplish throughout the multiple affected files (signing.cpp, signing_shares.h/cpp, quorums.h/cpp, and rpc/quorums.cpp), making it clearly on-topic and informative about the changeset's intent and implementation.
✨ 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 f075a12 and 0716c7a.

📒 Files selected for processing (1)
  • src/llmq/quorums.cpp (12 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.{cpp,h,cc,cxx,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.{cpp,h,cc,cxx,hpp}: Dash Core C++ codebase must be written in C++20 and require at least Clang 16 or GCC 11.1
Dash uses unordered_lru_cache for efficient caching with LRU eviction

Files:

  • src/llmq/quorums.cpp
🔇 Additional comments (5)
src/llmq/quorums.cpp (5)

260-260: LGTM! Move optimization properly enabled.

The removal of const from vecQuorums (line 260) and the change from const auto& to auto& (line 269) correctly address the previous critical issue. Now std::move(pQuorum) at line 296 properly invokes the move constructor, avoiding the atomic operations on the shared_ptr reference count that the PR aims to eliminate.

Also applies to: 269-269, 296-296


478-519: LGTM! Appropriate use of reference parameter.

The change from CQuorumCPtr pQuorum to const CQuorum& quorum is appropriate here since RequestQuorumData doesn't require ownership semantics. The const-correctness is maintained, and all field accesses have been correctly updated from pointer syntax (pQuorum->) to reference syntax (quorum.).


676-698: LGTM! Correct reference-based implementation.

The signature change to const CQuorum& quorum is appropriate, and the field access at line 698 has been correctly updated to use reference syntax. The const-correctness is properly maintained.


916-1037: LGTM! Correct move semantics and dereferencing.

The parameter change and lambda capture at line 927 correctly implement the move optimization. The dereferencing operations at lines 933 and 1009 (*pQuorum) are appropriate for passing the quorum to functions that now take const CQuorum& parameters. The shared_ptr remains valid throughout the lambda's execution, making this safe.


886-914: The original review comment's concern is not applicable to these call sites.

Both call sites use the quorum variable after the StartCachePopulatorThread() call:

  • Line 436: quorum is inserted into the cache and returned afterward
  • Line 845: pQuorum is accessed in subsequent operations (line 851+, line 855+)

Using std::move() at these call sites would transfer ownership and invalidate the variables, breaking the code. The current implementation without std::move() at the call sites is correct. The function's by-value parameter with move-into-lambda semantics remains a valid optimization that doesn't require changes at the call sites.

Likely an incorrect or invalid review comment.


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 (4)
src/llmq/signing.cpp (1)

676-689: Quorum selection + local capture looks good; minor readability nit.

The on-the-fly lambda returning CQuorumCPtr is fine and keeps scopes tight. Optional: make the type explicit (CQuorumCPtr quorum = …) for readability in this hot path.

src/llmq/quorums.h (1)

283-285: API changes align with move/reference strategy; add nodiscard to prevent ignored results.

  • RequestQuorumData(const CQuorum&, uint16_t, …) and Start*Thread signatures are coherent with the move into worker lambdas.
  • Recommend marking RequestQuorumData as [[nodiscard]]; its boolean is actionable and ignoring it can hide request throttling/failures.
-    bool RequestQuorumData(CNode* pfrom, CConnman& connman, const CQuorum& quorum, uint16_t nDataMask,
+    [[nodiscard]] bool RequestQuorumData(CNode* pfrom, CConnman& connman, const CQuorum& quorum, uint16_t nDataMask,
                            const uint256& proTxHash = uint256()) const;

Also consider [[nodiscard]] for CreateSigShare in signing_shares.h (it already returns std::optional).

Also applies to: 312-317, 314-317

src/llmq/quorums.cpp (1)

676-699: Guard against modulo by zero on validMembers.size().

nIndex % quorum.qc->validMembers.size() will UB if validMembers is empty (shouldn’t happen, but a defensive guard avoids rare crashes).

-    return nIndex % quorum.qc->validMembers.size();
+    const size_t nMembers = quorum.qc->validMembers.size();
+    assert(nMembers != 0);
+    return nMembers ? (nIndex % nMembers) : 0;
src/llmq/signing_shares.h (1)

436-440: Interfaces now mix moved shared_ptr and const references; looks coherent.

  • AsyncSign(CQuorumCPtr) by value enables caller std::move and avoids extra atomic ops.
  • ForceReAnnouncement/SelectMemberForRecovery taking const CQuorum& is appropriate.
    Optional: mark CreateSigShare(...) [[nodiscard]] to prevent silent drops of failures.
-    std::optional<CSigShare> CreateSigShare(const CQuorum& quorum, const uint256& id, const uint256& msgHash) const;
+    [[nodiscard]] std::optional<CSigShare> CreateSigShare(const CQuorum& quorum, const uint256& id, const uint256& msgHash) const;

Also applies to: 439-440, 443-444

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between feb5f0f and aa26747.

📒 Files selected for processing (6)
  • src/llmq/quorums.cpp (10 hunks)
  • src/llmq/quorums.h (2 hunks)
  • src/llmq/signing.cpp (2 hunks)
  • src/llmq/signing_shares.cpp (11 hunks)
  • src/llmq/signing_shares.h (2 hunks)
  • src/rpc/quorums.cpp (8 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.{cpp,h,cc,cxx,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.{cpp,h,cc,cxx,hpp}: Dash Core C++ codebase must be written in C++20 and require at least Clang 16 or GCC 11.1
Dash uses unordered_lru_cache for efficient caching with LRU eviction

Files:

  • src/llmq/signing_shares.h
  • src/llmq/signing.cpp
  • src/rpc/quorums.cpp
  • src/llmq/quorums.cpp
  • src/llmq/quorums.h
  • src/llmq/signing_shares.cpp
🧬 Code graph analysis (4)
src/llmq/signing_shares.h (1)
src/llmq/signing_shares.cpp (12)
  • AsyncSign (1510-1514)
  • AsyncSign (1510-1510)
  • CreateSigShare (1540-1610)
  • CreateSigShare (1540-1540)
  • ForceReAnnouncement (1613-1637)
  • ForceReAnnouncement (1613-1613)
  • HandleNewRecoveredSig (1639-1644)
  • HandleNewRecoveredSig (1639-1639)
  • SelectMemberForRecovery (846-859)
  • SelectMemberForRecovery (846-846)
  • TryRecoverSig (764-844)
  • TryRecoverSig (764-765)
src/rpc/quorums.cpp (1)
src/llmq/quorums.h (1)
  • nDataMask (102-102)
src/llmq/quorums.h (1)
src/llmq/quorums.cpp (8)
  • RequestQuorumData (478-519)
  • RequestQuorumData (478-479)
  • GetQuorumRecoveryStartOffset (676-699)
  • GetQuorumRecoveryStartOffset (676-676)
  • StartCachePopulatorThread (886-914)
  • StartCachePopulatorThread (886-886)
  • StartQuorumDataRecoveryThread (916-1037)
  • StartQuorumDataRecoveryThread (916-917)
src/llmq/signing_shares.cpp (2)
src/llmq/signhash.cpp (1)
  • SignHash (14-22)
src/llmq/signhash.h (1)
  • SignHash (24-46)
🪛 GitHub Actions: Clang Diff Format Check
src/llmq/signing_shares.h

[error] 1-1: Clang-format differences detected in src/llmq/signing_shares.h. Run the formatter to fix formatting mismatches.

src/rpc/quorums.cpp

[error] 1-1: Clang-format differences detected in src/rpc/quorums.cpp. Run the formatter to fix formatting mismatches.

src/llmq/quorums.cpp

[error] 1-1: Clang-format differences detected in src/llmq/quorums.cpp. Run the formatter to fix formatting mismatches.

src/llmq/signing_shares.cpp

[error] 1-1: Clang-format differences detected in src/llmq/signing_shares.cpp. Run the formatter to fix formatting mismatches.

⏰ 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: mac-build / Build source
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: linux64_sqlite-build / Build source
  • GitHub Check: linux64_ubsan-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: linux64_fuzz-build / Build source
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: Lint / Run linters
🔇 Additional comments (10)
src/llmq/signing.cpp (1)

736-739: Correct: avoid extra atomic ops by moving the shared_ptr into AsyncSign.

Passing a dereferenced quorum to ForceReAnnouncement and then moving the shared_ptr into AsyncSign is the right order and avoids post-move use. Nice micro‑opt.

Please double‑check no future edits access “quorum” after Line 739; a quick grep will prevent accidental use‑after‑move regressions.

src/rpc/quorums.cpp (2)

182-233: Consistent shift to reference semantics for CQuorum across RPC paths.

  • BuildQuorumInfo now takes const CQuorum&; member access updates are correct.
  • Callers dereference shared_ptrs appropriately: quorum_info, quorum_memberof, quorum_sign_helper, quorum_selectquorum, quorum_getdata.
    All good and lifetime-safe since sources are CQuorumCPtr held locally.

Given public RPC exposure, please smoke‑test:

  • quorum info: with includeSkShare=false/true (if this node is a member).
  • quorum sign … submit=false path (CreateSigShare).
  • quorum getdata with both QUORUM_VERIFICATION_VECTOR and ENCRYPTED_CONTRIBUTIONS masks.

Also applies to: 268-269, 426-429, 476-477, 745-747, 833-833


1-1: Verify formatting changes against CI results.

The sandbox environment does not have clang-format available to verify the formatting diffs. While the file exists and a .clang-format configuration is present, I cannot execute the formatter to confirm the claimed violations. Please run clang-format-16 -i src/rpc/quorums.cpp locally and review the git diff output, or check the CI results to confirm the exact formatting issues before applying fixes.

src/llmq/quorums.cpp (3)

478-519: RequestQuorumData refactor: parameter update is correct.

Switching to const CQuorum& and building the request with the new nDataMask parameter looks good. Logging and request de‑dupe remain intact.


886-914: Good use of move-capture for pQuorum into worker lambdas.

Moving CQuorumCPtr into StartCachePopulatorThread/StartQuorumDataRecoveryThread tasks eliminates extra atomic ops and lifetime issues. Access is pointer‑stable in the closures.

Please sanity‑run a node with -watchquorums and ensure recovery logs (“Start/Requested/Processed/Done”) appear as expected on rotation.

Also applies to: 916-937, 1009-1011


1-1: Run clang-format locally to fix formatting issues.

Formatting issues were detected in src/llmq/quorums.cpp. Evidence of trailing whitespace was found during inspection. Since clang-format is unavailable in the verification environment, please run the formatter locally and verify the changes:

clang-format -i src/llmq/quorums.cpp
git diff -- src/llmq/quorums.cpp

Commit the formatting changes to resolve the CI check.

src/llmq/signing_shares.cpp (3)

1510-1514: AsyncSign path: correct move into queue; CreateSigShare callsite aligns with refactor.

  • Moving CQuorumCPtr into pendingSigns avoids extra refcount traffic.
  • Dereferencing for CreateSigShare is consistent with the new signature.

Also applies to: 1521-1537


1540-1610: Refactor to const CQuorum& in signing logic is sound.

Member access changes (params, qc, members) are correct; TryRecoverSig and ForceReAnnouncement build SignHash with dereferenced quorum consistently. Single‑node quorum handling remains intact.

Please verify recovery still triggers at threshold by:

  • forcing a session to reach params.threshold and observing a recovered signature in logs.

Also applies to: 1613-1637, 760-767, 776-828, 801-810, 827-835


1-1: Manual verification required for clang-format diffs.

The clang-format tool is not available in the sandbox environment to verify the formatting issues. While manual inspection of src/llmq/signing_shares.cpp shows the copyright header and includes are clean (no trailing whitespace detected), I cannot confirm what clang-format diffs CI originally detected. Please run clang-format -i src/llmq/signing_shares.cpp locally and verify the file passes CI formatting checks.

src/llmq/signing_shares.h (1)

1-1: Unable to verify clang-format violations in the sandbox (clang-format tool not available). The file inspection shows proper Unix line endings and no visible trailing whitespace on the copyright header. However, without executing clang-format locally, the actual formatting violations cannot be confirmed.

Please run clang-format -i src/llmq/signing_shares.h and git diff -- src/llmq/signing_shares.h locally to verify whether formatting changes are actually needed.

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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa26747 and f075a12.

📒 Files selected for processing (1)
  • src/llmq/quorums.cpp (11 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.{cpp,h,cc,cxx,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.{cpp,h,cc,cxx,hpp}: Dash Core C++ codebase must be written in C++20 and require at least Clang 16 or GCC 11.1
Dash uses unordered_lru_cache for efficient caching with LRU eviction

Files:

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

[error] 1-1: Clang format differences found. Command failed: git diff -U0 origin/develop -- $(git ls-files -- $(cat test/util/data/non-backported.txt)) | ./contrib/devtools/clang-format-diff.py -p1 > diff_output.txt

⏰ 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: mac-build / Build source
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: linux64_ubsan-build / Build source
  • GitHub Check: linux64_fuzz-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: linux64_sqlite-build / Build source
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: Lint / Run linters
🔇 Additional comments (5)
src/llmq/quorums.cpp (5)

478-494: Excellent refactor to eliminate unnecessary reference counting.

Changing the parameter from CQuorumCPtr (shared pointer) to const CQuorum& (reference) is a good optimization since this function only reads from the quorum and doesn't need ownership semantics. This avoids atomic increment/decrement operations on the control block.


676-698: Good refactor to use const reference.

Similar to RequestQuorumData, this change eliminates unnecessary shared_ptr operations for a read-only function.


886-913: LGTM! This achieves the move optimization for async tasks.

The changes here correctly implement the optimization described in the PR:

  • Taking CQuorumCPtr by value (line 886) enables the caller to move in
  • Capturing by move in the lambda (line 899) transfers ownership to the async task
  • This avoids the atomic increment/decrement pair that would occur with const reference + copy

916-1037: LGTM! Consistent move optimization for async recovery.

The changes mirror the pattern in StartCachePopulatorThread:

  • Pass-by-value parameter enables move semantics (line 916-917)
  • Lambda move capture transfers ownership (line 927)
  • Dereferences on lines 933 and 1009 are consistent with updated function signatures

The &connman capture by reference is safe since the worker pool is stopped in the destructor.


1-1: Address clang-format issues.

The pipeline is reporting clang-format differences. Please run the clang-format tool to fix formatting issues before merging.

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 0716c7a

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.

2 participants