Skip to content

Add desktop handlers for XpubAnnounced and DescriptorAcked events#279

Merged
kwsantiago merged 5 commits intomainfrom
desktop-handlers
Feb 26, 2026
Merged

Add desktop handlers for XpubAnnounced and DescriptorAcked events#279
kwsantiago merged 5 commits intomainfrom
desktop-handlers

Conversation

@wksantiago
Copy link
Contributor

@wksantiago wksantiago commented Feb 26, 2026

Summary

  • Add XpubAnnounced desktop handler and fix stale frost_node on reconnect
  • Add DescriptorAcked event and track ack progress in UI

Summary by CodeRabbit

  • New Features

    • Show descriptor acknowledgment progress (received vs expected) during wallet setup.
    • Forward descriptor-related and xpub announcement events to the wallet flow so progress and announcements are reflected in the UI.
  • Bug Fixes

    • Improved event queue robustness and warnings on failure conditions.
    • Clear coordination and node state on disconnect/reconnect to avoid stale UI state.
    • Ignore invalid-network contributions with a warning.

@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 2026

Warning

Rate limit exceeded

@kwsantiago has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 7 minutes and 53 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 1cfd519 and c8f16e4.

📒 Files selected for processing (2)
  • keep-desktop/src/frost.rs
  • keep-frost-net/src/node/descriptor.rs

Walkthrough

This PR adds DescriptorAcked and XpubAnnounced events, propagates ack/expected-ack counts through descriptor finalization, updates FROST event handling in the desktop client, and improves reconnection cleanup and descriptor progress reporting. (48 words)

Changes

Cohort / File(s) Summary
Desktop FROST integration
keep-desktop/src/frost.rs
Robustified event queue handling on mutex poison; frost_event_listener forwards DescriptorAcked and XpubAnnounced; spawns descriptor finalization task on DescriptorReady; updates wallet progress (WaitingAcks/Failed); clears frost_node and active coordinations on disconnect/reconnect.
Message types (desktop)
keep-desktop/src/message.rs
Added DescriptorAcked { session_id, share_index, ack_count, expected_acks } and XpubAnnounced { share_index, recovery_xpubs } to FrostNodeMsg; extended Debug formatting.
UI enum formatting
keep-desktop/src/screen/wallet.rs
Reformatted DescriptorProgress variants WaitingContributions and WaitingAcks to inline struct-like variants (no semantic change).
Descriptor session accessors
keep-frost-net/src/descriptor_session.rs
Added pub fn ack_count(&self) -> usize and pub fn expected_ack_count(&self) -> usize to expose ACK metrics.
Node descriptor logic
keep-frost-net/src/node/descriptor.rs
Now computes and propagates (is_complete, ack_count, expected_acks) when handling descriptor ACKs; emits DescriptorAcked events; build_and_finalize_descriptor now returns usize (expected ACK count); changed xpub announce storage eviction logic; various small flow and serialization adjustments.
Node event types (core)
keep-frost-net/src/node/mod.rs
Added DescriptorAcked { session_id, share_index, ack_count, expected_acks } to KfpNodeEvent and extended Debug formatting.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Desktop as Desktop Client
participant Frost as Frost Node Handle
participant Node as keep-frost-net Node
participant Session as DescriptorSession
participant UI as Wallet UI

Desktop->>Frost: listen for KfpNodeEvent / Frost events
Frost->>Node: receive descriptor messages / ACKs
Node->>Session: process ACK -> update acks & expected_acks
Session-->>Node: ack_count, expected_acks
Node-->>Frost: emit DescriptorAcked(session_id, share_index, ack_count, expected_acks)
Frost-->>Desktop: Frost event DescriptorAcked
Desktop->>UI: push WalletDescriptorProgress (WaitingAcks with received/expected)
Desktop->>Frost: on DescriptorReady spawn build_and_finalize_descriptor task
Node->>Node: build_and_finalize_descriptor -> returns expected_acks
Note over Desktop,UI: disconnect/reconnect clears frost_node and active_coordinations

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped through events, sent ACKs in time,
I nudged descriptors to form and chime,
Queues now sturdy, reconnects made neat,
Xpubs announced — a tidy feat,
Wallets bloom with progress, hop, and rhyme.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary changes: adding desktop event handlers for XpubAnnounced and DescriptorAcked events, which are the core additions across frost.rs and message.rs files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch desktop-handlers

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.

@wksantiago wksantiago self-assigned this Feb 26, 2026
@wksantiago wksantiago linked an issue Feb 26, 2026 that may be closed by this pull request
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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
keep-frost-net/src/node/descriptor.rs (1)

753-785: ⚠️ Potential issue | 🟠 Major

Suppress duplicate ACK progress events to prevent stale downstream state updates.

add_ack is idempotent for duplicate senders, but this block still emits DescriptorAcked (and can re-emit DescriptorComplete) when no new ACK was added. That creates redundant/noisy progress events and can cause UI state regressions after completion.

Proposed fix
-        let (is_complete, ack_count, expected_acks) = {
+        let (is_complete, ack_count, expected_acks, progressed) = {
             let mut sessions = self.descriptor_sessions.write();
             let session = sessions
                 .get_session_mut(&payload.session_id)
                 .ok_or_else(|| FrostNetError::Session("unknown descriptor session".into()))?;
+            let before = session.ack_count();

             session.add_ack(
                 share_index,
                 payload.descriptor_hash,
                 &payload.key_proof_psbt,
             )?;
+            let ack_count = session.ack_count();
             (
                 session.is_complete(),
-                session.ack_count(),
+                ack_count,
                 session.expected_ack_count(),
+                ack_count > before,
             )
         };
+
+        if !progressed {
+            return Ok(());
+        }

         info!(
             session_id = %hex::encode(payload.session_id),
             share_index,
             ack_count,
             expected_acks,
             complete = is_complete,
             "Received descriptor ACK"
         );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@keep-frost-net/src/node/descriptor.rs` around lines 753 - 785, Summary: avoid
emitting DescriptorAcked/DescriptorComplete when add_ack was idempotent and no
new ACK was added. Fix: inside the block that locks descriptor_sessions and
obtains session via get_session_mut(&payload.session_id), read the session's
current ack count and completion state (e.g., let prev_ack_count =
session.ack_count(); let prev_complete = session.is_complete()) before calling
session.add_ack(...); call session.add_ack(...); then compute the new ack_count,
expected_acks, and is_complete and only send KfpNodeEvent::DescriptorAcked if
ack_count > prev_ack_count; likewise only emit DescriptorComplete when
is_complete is true and prev_complete was false. Reference symbols:
descriptor_sessions, get_session_mut, add_ack, ack_count, is_complete,
expected_ack_count, KfpNodeEvent::DescriptorAcked, DescriptorComplete.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@keep-frost-net/src/node/descriptor.rs`:
- Around line 753-785: Summary: avoid emitting
DescriptorAcked/DescriptorComplete when add_ack was idempotent and no new ACK
was added. Fix: inside the block that locks descriptor_sessions and obtains
session via get_session_mut(&payload.session_id), read the session's current ack
count and completion state (e.g., let prev_ack_count = session.ack_count(); let
prev_complete = session.is_complete()) before calling session.add_ack(...); call
session.add_ack(...); then compute the new ack_count, expected_acks, and
is_complete and only send KfpNodeEvent::DescriptorAcked if ack_count >
prev_ack_count; likewise only emit DescriptorComplete when is_complete is true
and prev_complete was false. Reference symbols: descriptor_sessions,
get_session_mut, add_ack, ack_count, is_complete, expected_ack_count,
KfpNodeEvent::DescriptorAcked, DescriptorComplete.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ea12fca and 3ec41f6.

📒 Files selected for processing (6)
  • keep-desktop/src/frost.rs
  • keep-desktop/src/message.rs
  • keep-desktop/src/screen/wallet.rs
  • keep-frost-net/src/descriptor_session.rs
  • keep-frost-net/src/node/descriptor.rs
  • keep-frost-net/src/node/mod.rs

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@keep-desktop/src/frost.rs`:
- Around line 966-968: handle_reconnect_relay currently resets
frost_node/pending state but omits clearing self.active_coordinations, which can
leak stale sessions; update handle_reconnect_relay to mirror the disconnect-path
cleanup by acquiring the same lock(s) and clearing or reinitializing
self.active_coordinations (and any related pending coordination structures
touched in the 969-976 block) so no old coordination entries survive the
reconnect cycle.

In `@keep-frost-net/src/node/descriptor.rs`:
- Around line 903-906: The current logic in seen_xpub_announces that returns
Ok(()) when seen.len() >= 10_000 drops incoming announces and allows easy
saturation; instead, evict the oldest entry from the dedupe cache before
inserting the new announce so the cache stays capped but continues accepting
messages. Locate the capacity check around seen_xpub_announces (the block that
does if seen.len() >= 10_000 { tracing::warn!(...) ; return Ok(()); }) and
replace the early return with an eviction operation on the underlying data
structure (e.g., remove or pop the oldest key/entry) and then proceed to insert
the new announce, keeping the warn log to record the eviction event.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3ec41f6 and 1cfd519.

📒 Files selected for processing (6)
  • keep-desktop/src/frost.rs
  • keep-desktop/src/message.rs
  • keep-desktop/src/screen/wallet.rs
  • keep-frost-net/src/descriptor_session.rs
  • keep-frost-net/src/node/descriptor.rs
  • keep-frost-net/src/node/mod.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • keep-desktop/src/screen/wallet.rs

@kwsantiago kwsantiago merged commit 4dee8b1 into main Feb 26, 2026
9 checks passed
@kwsantiago kwsantiago deleted the desktop-handlers branch February 26, 2026 17:31
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.

Wire desktop wallet coordination handlers

2 participants