Skip to content

fix(platform-wallet): survive an ambiguous re-broadcast when resuming a Built asset lock - #4367

Merged
QuantumExplorer merged 1 commit into
v4.2-devfrom
fix/asset-lock-built-resume-maybesent
Aug 11, 2026
Merged

fix(platform-wallet): survive an ambiguous re-broadcast when resuming a Built asset lock#4367
QuantumExplorer merged 1 commit into
v4.2-devfrom
fix/asset-lock-built-resume-maybesent

Conversation

@QuantumExplorer

@QuantumExplorer QuantumExplorer commented Aug 11, 2026

Copy link
Copy Markdown
Member

Extracts the still-needed half of #4337 onto current v4.2-dev (authorship preserved — the commit is @HashEngineering's, adapted from #4337's head).

Why #4337 was split

#4337 fixed two independent ways an asset-lock top-up could never finish. Its first half — classifying Platform's "already completely used" rejection and settling the tracked lock — is superseded by #4357 (merged 2026-08-11), whose shared reconcile_asset_lock_submit_result covers the same rejection across all four funded flows with outpoint binding and a safer policy: the unauthenticated verdict never tombstones the lock; it is preserved as RecoveredFromChain / consumption-unknown with a ChainLock proof, surfacing the same typed code 24.

This PR carries the second half, which #4357 does not touch.

The remaining bug

The Built arm of resume_asset_lock propagated every broadcast error, including MaybeSent. For a lock stuck at Built whose transaction was broadcast — the app died between the send and the status advance — MaybeSent is the expected answer on every retry: the network already holds the tx, so each re-broadcast draws the same ambiguity. The resume failed, the lock stayed Built, every recovery pass repeated the same abort, and the top-up never completed. Observed live on an Android testnet wallet (the same incident that produced #4337).

The fix

Only a definite Rejected (provably never entered the send pipeline) stops the resume. MaybeSent logs, advances the lock to Broadcast, and proceeds to the proof wait — exactly what the Broadcast arm already does with the identical signal. A genuinely un-broadcast tx still fails definitively and stays resumable at Built.

Two regression tests cover the ambiguous and definite branches, asserting the resulting lock status as well as the error (built_resume_survives_an_ambiguous_rebroadcast_and_advances, built_resume_still_fails_on_a_definite_rejection).

Note for reviewers: #4355 (open) touches the same Built arm to wait for SPV transport before this broadcast; the changes compose but whichever lands second needs a trivial rebase.

Verification

  • cargo test -p platform-wallet --lib — 654 passed, 0 failed (both new tests included)
  • cargo clippy -p platform-wallet --all-targets — no new warnings (1 pre-existing on the unmodified base)
  • cargo fmt --all — clean

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved asset lock recovery when a broadcast may have been sent but its outcome is uncertain.
    • Ambiguous broadcasts now continue processing while awaiting confirmation instead of stopping prematurely.
    • Definite broadcast rejections continue to fail safely without advancing the asset lock.

… a Built asset lock

Extracted from #4337; its already-consumed half is superseded by the
merged #4357.

The Built arm of resume_asset_lock propagated every broadcast error,
including MaybeSent. For a lock stuck at Built whose transaction WAS
broadcast (the app died between the send and the status advance),
MaybeSent is the expected answer on every retry — the network already
holds the tx, so each re-broadcast draws the same ambiguity. The resume
failed, the lock stayed Built, every recovery pass repeated the same
abort, and the top-up never completed. Observed live on an Android
testnet wallet.

Only a definite Rejected now stops the resume; MaybeSent advances the
lock to Broadcast and proceeds to the proof wait, matching what the
Broadcast arm already does with the identical signal and keeping a
genuinely un-broadcast tx resumable at Built.

Tests: two regression tests covering the ambiguous and definite
branches, asserting the status transition as well as the error.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added this to the v4.2.0 milestone Aug 11, 2026
@thepastaclaw

thepastaclaw commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

🕓 Ready for review — 1 ahead in queue (commit 6d4bebd)
Queue position: 2/2 · 1 review active
ETA: start ~10:45 UTC · complete ~10:56 UTC (median 11m across 30 recent reviews; 2 slots)
Queued 56s ago · Last checked: 2026-08-11 10:40 UTC

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ef38d3a3-a29f-4d1c-b71d-5f4ba82718e9

📥 Commits

Reviewing files that changed from the base of the PR and between 08edcfd and 6d4bebd.

📒 Files selected for processing (1)
  • packages/rs-platform-wallet/src/wallet/asset_lock/sync/recovery.rs

📝 Walkthrough

Walkthrough

Asset-lock recovery now distinguishes ambiguous MaybeSent rebroadcast results from definite broadcast failures. Ambiguous results transition locks to Broadcast and wait for proof. Definite failures retain Built. Tests cover both outcomes.

Changes

Asset-lock recovery

Layer / File(s) Summary
Handle rebroadcast outcomes
packages/rs-platform-wallet/src/wallet/asset_lock/sync/recovery.rs
Built recovery treats BroadcastError::MaybeSent as submitted, transitions to Broadcast, and continues waiting for proof. Other broadcast errors still abort recovery.
Validate recovery outcomes
packages/rs-platform-wallet/src/wallet/asset_lock/sync/recovery.rs
Shared test setup and tests verify ambiguous rebroadcasts reach Broadcast after proof wait, while definite rejections return an error and retain Built.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Recovery
  participant Broadcaster
  participant ProofWait
  participant LockTracker
  Recovery->>Broadcaster: Resume Built lock
  Broadcaster-->>Recovery: MaybeSent
  Recovery->>LockTracker: Set lock to Broadcast
  Recovery->>ProofWait: Wait for proof
  ProofWait-->>LockTracker: Proof wait timeout
Loading

Possibly related PRs

Suggested reviewers: lklimek, llbartekll, shumkov

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: handling ambiguous re-broadcasts when resuming a Built asset lock.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/asset-lock-built-resume-maybesent

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

@QuantumExplorer
QuantumExplorer merged commit 1c68132 into v4.2-dev Aug 11, 2026
19 checks passed
@QuantumExplorer
QuantumExplorer deleted the fix/asset-lock-built-resume-maybesent branch August 11, 2026 10:46
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