Skip to content

feat(wallet): chain-order the shielded Date-unknown band; trust SDK asset-lock reconstruction - #943

Merged
QuantumExplorer merged 2 commits into
developfrom
claude/exciting-goldstine-74cfda
Aug 9, 2026
Merged

feat(wallet): chain-order the shielded Date-unknown band; trust SDK asset-lock reconstruction#943
QuantumExplorer merged 2 commits into
developfrom
claude/exciting-goldstine-74cfda

Conversation

@QuantumExplorer

@QuantumExplorer QuantumExplorer commented Aug 8, 2026

Copy link
Copy Markdown
Member

Consumes platform dashpay/platform#4342 (SDK tracked-asset-lock reconstruction after restore + minNotePosition/hasMinNotePosition on scan-derived shielded entries). Requires a ../platform checkout at v4.2-dev71402fae82 and a rebuilt DashSDKFFI.xcframework; for restored locks to actually surface at statusRaw 5 (rather than 1/3), the checkout must also carry dashpay/platform#4347. This PR is forward-compatible either way — merge order doesn't matter.

1. "Date unknown" band ordered by true chain order

The trailing unknown-date history band (#940) previously kept arbitrary order among its entries (all share the .distantPast sort sentinel). Now:

  • ShieldedActivityItem snapshots the SDK row's minNotePosition — the smallest commitment-tree position among the entry's own received notes, an exact append-only chain-order key (nil on live-recorded entries and rows persisted before the field existed).
  • TransactionListDataItem.chainOrderKey exposes it; HomeViewModel's pre-grouping sort tiebreaks equal dates by it descending, so the band reads newest-first in true on-chain sequence, identically on every device restoring the same seed.

2. Restore fallback trimmed to a diagnostic

SDK reconstruction now writes store-backed PersistentAssetLock rows for historical funding txs, so #939's app-side raw-tx reparse (addReconstructedLocks) is dead weight — store rows always won over it. It is replaced by logUnclassifiedAssetLocks, which logs any persisted asset-lock tx with no store row as a reconstruction gap. The reconstructedUnknownFundingType/reconstructedStatus sentinels, reconstructedLockInfo, and Transaction.reconstructedLockAmountDuffs are removed. statusRaw 5 (RecoveredFromChain) is handled explicitly: snapshot dedup prefers consumed (4) over recovered (5), and the detail sheet shows an honest "Restored — completion unknown".

Verification (restored testnet wallet, QA simulator)

Deleted the testnet derived state while keeping the keychain seed → the host's reinstall-recovery path re-imported the wallet and full-scanned from the import floor:

  • 9/9 asset-lock funding txs got store rows with exact funding types (1 identity-registration, 2 platform, 6 shielded); the coverage diagnostic stayed silent → removing the fallback loses nothing.
  • Scan-derived shielded entry landed honest: createdAtMs = 0 with minNotePosition set, feeding the new sort.
  • ⚠️ Found an SDK-side gap in #4342: reconstructed rows arrive at statusRaw 1 (Broadcast) in-session and only reach 3 (ChainLocked) after a restart — never the intended 5 — because chainlock promotion (ChainLockProcessed) never re-flows through enrich_from_record, and the enrich path upgrades to ChainLocked rather than RecoveredFromChain. Both 1 and 3 sit in the app's pending window, so restored wallets show false "Pending" pills. Fixed SDK-side in fix(platform-wallet): finalize reconstructed asset locks as RecoveredFromChain, in-session platform#4347: on a re-verified fresh restore, all 9 locks now reach statusRaw 5 + chain proof in-session (upgraded by the new ChainLockProcessed enrichment). A second commit here widens the registration-recovery lookup to include status-5 locks so a stranded registration payment keeps its recovery path.

Canonical dashpay simulator build is green. Unit-test target remains broken repo-wide (pre-existing).

🤖 Generated with Claude Code

…ck reconstruction

Consumes platform #4342 (SDK-side tracked-asset-lock reconstruction +
minNotePosition on scan-derived shielded entries):

- The trailing "Date unknown" history band (PR #940) now orders by exact
  on-chain sequence: ShieldedActivityItem carries the SDK's
  minNotePosition (smallest note commitment-tree position, nil when the
  row predates the field), TransactionListDataItem exposes it as
  chainOrderKey, and the pre-grouping sort tiebreaks equal dates by it
  descending — identical order on every device that restores the seed.

- The app-side restore fallback (PR #939's addReconstructedLocks raw-tx
  reparse) is reduced to a coverage diagnostic: SDK reconstruction now
  writes store-backed PersistentAssetLock rows for every historical
  funding tx (verified 9/9 on a restored testnet wallet — identity,
  platform, and shielded types all classify), and store rows always won
  over the fallback anyway. Any asset-lock tx with no row is logged as a
  reconstruction gap. The reconstructed* sentinels and
  Transaction.reconstructedLockAmountDuffs go with it.

- statusRaw 5 (RecoveredFromChain) is mapped explicitly: dedup prefers
  consumed (4) over recovered (5), and the tx detail sheet shows
  "Restored — completion unknown" instead of falling through. Note the
  SDK currently delivers reconstructed rows at 1/3, not 5 — the false-
  pending consequence and the enrichment gap are SDK-side, tracked for a
  platform follow-up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@QuantumExplorer, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 9 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0d1d3e81-cd0a-4879-af82-0a78998f0b24

📥 Commits

Reviewing files that changed from the base of the PR and between caadaab and 0d00929.

📒 Files selected for processing (9)
  • DashWallet/Sources/Infrastructure/SwiftDashSDK/Identity/DWIdentityRegistrationCoordinator.swift
  • DashWallet/Sources/Infrastructure/SwiftDashSDK/PlatformAddressSyncCoordinator.swift
  • DashWallet/Sources/Models/Transactions/Model/Transaction.swift
  • DashWallet/Sources/UI/Home/Views/HomeViewModel.swift
  • DashWallet/Sources/UI/Home/Views/ShieldedActivityHistory.swift
  • DashWallet/Sources/UI/Home/Views/TransactionListDataItem.swift
  • DashWallet/Sources/UI/Payments/InternalTransfer/InternalTransferConfirmSheet.swift
  • DashWallet/Sources/UI/Tx/Details/Model/TxDetailModel.swift
  • DashWallet/en.lproj/Localizable.strings

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

@QuantumExplorer QuantumExplorer changed the title feat(shielded): chain-order the Date-unknown band; trust SDK asset-lock reconstruction feat(wallet): chain-order the shielded Date-unknown band; trust SDK asset-lock reconstruction Aug 8, 2026
With platform #4347, a registration asset lock stranded by an app kill
whose block chain-locks before relaunch surfaces as statusRaw 5
(RecoveredFromChain) instead of staying in the 0…3 window the recovery
lookup filtered on — the stranded payment would have stopped being
offered for recovery. Treat everything but the Consumed (4) tombstone
as unfinished: a 5-lock with no identity is a genuinely incomplete
registration, and the SDK resume path explicitly supports consuming it.
Completed registrations never resume from this lock — both call sites
probe the identity (local row, then the Platform slot, reconciling the
lock to Consumed) first.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@QuantumExplorer
QuantumExplorer merged commit b326045 into develop Aug 9, 2026
4 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.

1 participant