Skip to content

fix(wallet): report authoritative L1 broadcast outcomes#4181

Closed
llbartekll wants to merge 1 commit into
v4.1-devfrom
codex/l1-broadcast-outcomes
Closed

fix(wallet): report authoritative L1 broadcast outcomes#4181
llbartekll wants to merge 1 commit into
v4.1-devfrom
codex/l1-broadcast-outcomes

Conversation

@llbartekll

@llbartekll llbartekll commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • use DAPI/Core as the L1 transaction acceptance authority
  • expose accepted, rejected, and unknown outcomes through Rust, FFI, and Swift
  • relay through SPV and apply locally only after Core acceptance
  • reconcile UTXO reservations according to definitive versus ambiguous failures
  • adapt both legacy CoreTransaction and current atomic FinalizedCoreTransaction flows
  • prevent the Swift Example App from reporting success without Core acceptance

ABI note

The current v4.1-dev branch already assigns code 22 to CoreInsufficientFunds and codes 23 through 25 to asset-lock errors. TransactionBroadcastRejected therefore uses the next free stable code, 26. TransactionBroadcastUnconfirmed remains code 20.

Tests

  • platform-wallet broadcaster tests: 9 passed
  • SPV runtime tests: 3 passed
  • UTXO reservation tests: 2 passed
  • platform-wallet-ffi broadcast tests: 5 passed
  • rejected error-code mapping test: passed
  • cargo fmt --all -- --check

Summary by CodeRabbit

  • New Features

    • Added authoritative transaction broadcast outcomes: accepted, rejected, or unknown.
    • Added dedicated handling and messaging for transactions definitively rejected by Core.
    • Added outcome-based broadcast APIs while retaining deprecated compatibility methods.
    • Improved send status messaging to distinguish successful, rejected, and uncertain broadcasts.
  • Bug Fixes

    • Transactions now include their ID for rejected or uncertain network outcomes.
    • Uncertain broadcasts are reconciled before reporting status, reducing incorrect success or rejection results.
    • SPV relay failures no longer override confirmed Core acceptance.

@coderabbitai

coderabbitai Bot commented Jul 21, 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

Run ID: bcf21e58-cf69-4810-a421-e1bb12171250

📥 Commits

Reviewing files that changed from the base of the PR and between 8b466ab and e03f870.

📒 Files selected for processing (19)
  • packages/rs-platform-wallet-ffi/src/core_wallet/broadcast.rs
  • packages/rs-platform-wallet-ffi/src/error.rs
  • packages/rs-platform-wallet/src/broadcaster.rs
  • packages/rs-platform-wallet/src/manager/load.rs
  • packages/rs-platform-wallet/src/manager/wallet_lifecycle.rs
  • packages/rs-platform-wallet/src/spv/runtime.rs
  • packages/rs-platform-wallet/src/test_support.rs
  • packages/rs-platform-wallet/src/wallet/asset_lock/sync/recovery.rs
  • packages/rs-platform-wallet/src/wallet/platform_addresses/provider.rs
  • packages/rs-platform-wallet/src/wallet/platform_addresses/transfer.rs
  • packages/rs-platform-wallet/src/wallet/platform_addresses/wallet.rs
  • packages/rs-platform-wallet/src/wallet/platform_addresses/withdrawal.rs
  • packages/rs-platform-wallet/src/wallet/reservations.rs
  • packages/rs-platform-wallet/src/wallet/shielded/viewing_key_bind_tests.rs
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/CoreWallet/ManagedCoreWallet.swift
  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletResult.swift
  • packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Core/ViewModels/SendViewModel.swift
  • packages/swift-sdk/SwiftExampleApp/SwiftExampleAppTests/SendViewModelCoreRecipientsTests.swift
  • packages/swift-sdk/SwiftTests/SwiftDashSDKTests/ErrorHandlingTests.swift

📝 Walkthrough

Walkthrough

Broadcasting now treats Dash Core acceptance as authoritative, reconciles uncertain submissions, preserves local transaction IDs for network outcomes, exposes dedicated rejection results through FFI and Swift, and updates the example send flow and wallet wiring.

Changes

Broadcast authority and relay

Layer / File(s) Summary
Core acceptance and relay classification
packages/rs-platform-wallet/src/broadcaster.rs, packages/rs-platform-wallet/src/spv/runtime.rs, packages/rs-platform-wallet/src/wallet/...
DAPI submission now classifies accepted, rejected, and uncertain results, reconciles uncertain submissions with getTransaction, and performs SPV relay only after Core acceptance.
Broadcaster dependency wiring
packages/rs-platform-wallet/src/manager/..., packages/rs-platform-wallet/src/test_support.rs, packages/rs-platform-wallet/src/wallet/platform_addresses/..., packages/rs-platform-wallet/src/wallet/shielded/...
Wallet constructors and test fixtures pass the SDK dependency to SpvBroadcaster.
FFI result and txid propagation
packages/rs-platform-wallet-ffi/src/core_wallet/broadcast.rs, packages/rs-platform-wallet-ffi/src/error.rs
FFI broadcast functions return classified result codes and local txids for network outcomes, while operational errors leave the txid null. Definitive rejection receives a dedicated code.
Swift outcome API and UI mapping
packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/..., packages/swift-sdk/SwiftExampleApp/...
Swift exposes typed broadcast outcomes, maintains deprecated compatibility wrappers, and maps Core outcomes to send success or error messages with coverage tests.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

Possibly related PRs

  • dashpay/platform#3970 — Updates the same FFI broadcast function’s result and out_txid handling.
  • dashpay/platform#3985 — Introduces the rejected-versus-maybe-sent classification that this change propagates through FFI and higher layers.

Suggested reviewers: shumkov, lklimek, quantumexplorer, zocolini

Sequence Diagram(s)

sequenceDiagram
  participant SendViewModel
  participant ManagedCoreWallet
  participant DapiBroadcaster
  participant SpvRuntime
  SendViewModel->>ManagedCoreWallet: broadcastTransactionWithOutcome
  ManagedCoreWallet->>DapiBroadcaster: submit transaction
  DapiBroadcaster->>DapiBroadcaster: reconcile uncertain Core response
  DapiBroadcaster->>SpvRuntime: relay after Core acceptance
  DapiBroadcaster-->>ManagedCoreWallet: broadcast result and txid
  ManagedCoreWallet-->>SendViewModel: accepted, rejected, or unknown outcome
Loading
🚥 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 is concise and accurately summarizes the main change: authoritative L1 broadcast outcome reporting in the wallet.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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 codex/l1-broadcast-outcomes

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.

@github-actions github-actions Bot added this to the v4.1.0 milestone Jul 21, 2026
@thepastaclaw

thepastaclaw commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

🔍 Review in progress — actively reviewing now (commit e03f870)
Stage: Codex precheck starting
ETA: complete ~19:35 UTC (median 30m across 30 recent reviews)
Running 15m · Last checked: 2026-07-22 19:20 UTC

@QuantumExplorer

Copy link
Copy Markdown
Member

This is the wrong approach, this should be fixed in rust dash core.

@QuantumExplorer

Copy link
Copy Markdown
Member

Actually there are parts here that are useful, reopening.

@QuantumExplorer

Copy link
Copy Markdown
Member

Superseded by #4198, which carries this PR's DAPI classification, getTransaction reconciliation, FFI/Swift outcome plumbing, and UTXO reservation handling forward on top of dashpay/rust-dashcore#913 — dash-spv now provides a trustless peer-echo acceptance signal (send to a subset of peers, a withheld peer announcing the txid back proves network acceptance), which #4198 uses as the fallback authority when DAPI is ambiguous or unreachable. Closing rather than rebasing since the SPV-side rework replaces this branch's core relay logic.

bfoss765 pushed a commit to bfoss765/platform that referenced this pull request Jul 23, 2026
…allback

Network acceptance, not a successful peer socket write, now decides what a
broadcast reports. Two authorities establish it:

- DAPI/Core (primary): single-attempt submission through DAPI's Core
  sendrawtransaction bridge, classified accepted / already-known / rejected /
  uncertain from the gRPC code, with uncertain submissions reconciled via
  getTransaction.
- SPV peer echo (trustless fallback): when DAPI is ambiguous or unreachable,
  the wallet falls back to dash-spv's broadcast acceptance detection
  (dashpay/rust-dashcore#913) — the transaction is sent to a subset of SPV
  peers and a withheld peer announcing the txid back proves it propagated
  into network mempools. A p2p reject resolves Rejected; no signal within
  30s resolves MaybeSent.

Rejected releases the transaction's UTXO reservation for immediate retry;
MaybeSent keeps it (double-spend guard). Accepted transactions are relayed
through SPV best-effort so the local mempool pipeline sees them immediately;
a relay failure never downgrades an authoritative accept.

The outcome surfaces through FFI as a dedicated rejection code (26) with the
txid preserved on all network outcomes, and in Swift as
CoreTransactionBroadcastOutcome (accepted/rejected/unknown) via
broadcastTransactionWithOutcome, so the example app can no longer report
payment success without network acceptance.

Bumps rust-dashcore to 58f207e5 (dashpay/rust-dashcore#913).

Supersedes dashpay#4181; carries over its DAPI classification, getTransaction
reconciliation, FFI/Swift outcome plumbing, and reservation reconciliation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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