Skip to content

Shielded sync: recover a rejected persistence round before publishing later watermarks #5695

Open

Description

@PastaPastaPasta

Problem

A shielded sync pass commits its receipts and advances each subwallet's watermark in the Rust store, then delivers the changeset to the host. If the host rejects that round, FFIPersister rolls it back and keeps nothing, and the coordinator's delivery (queue_pass_changeset, and the sync() fan-out before #5277) only logs the error. Causes include a SwiftData save() failing in endChangeset, any callback in the round failing, or, since #5277, a failed existing-row read in persistShieldedNotes. The receipts are then in memory but not on the host. The next pass skips them because they are below the in-memory watermark, yet still publishes the advanced watermark. After a restart, restore trusts that durable watermark, so the missing notes, with their balance and receipt history, stay missing until an explicit rescan.

This predates #5277: any failed round already leaves this gap. #5277 adds one more way for a round to fail.

Proposed direction

Keep failed publication recoverable in the Rust coordinator and persistence layer:

  • Retain a rejected round's changeset, or mark the affected subwallets dirty, and re-deliver it before or merged with the next round, following the backend's retry classification (PlatformWalletPersistRC.transient vs fatal).
  • Never publish a durable watermark beyond receipts that haven't reached the host. For example, hold the published watermark at the lowest unpublished receipt position until it lands, or rewind the in-memory watermark when a round fails so the next pass re-delivers those receipts.

Tests: reject a receipt round, run a successful pass, then restore from the resulting host state; the note must be present.

Raised in review of #5277 (#5277 (comment)).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions