Skip to content

SDK recovery primitive: proposal-embedded note import #415

Description

@haseebrabbani

Sub-issue of #357. Spike #412 validated the reconstruction path; this issue productizes it as an SDK recovery primitive.

Context

v2 consume_notes proposals embed serialized note bytes (consume_notes_notes, base64 Note serialization, introduced by #229). After recovery, pending proposals are already restored via syncProposals() — the embedded note bytes are opportunistic recovery material for notes the account was in the middle of consuming.

Spike findings (#412), on a fresh store against testnet:

  • Local note bytes + node-fetched inclusion proof → NoteFile::NoteWithProof import succeeds without using any node-held body; the record lands in Unverified state and the next sync verifies it. This works for private notes too — the node serves inclusion proofs without bodies (FetchedNote::Private).
  • An uncommitted note returns 0 results from get_notes_by_id — cleanly classifiable as not-committed/retryable, no error — and can be parked in Expected state via a NoteDetails import.
  • import_notes batches are atomic upstream: one invalid note fails the whole batch. Imports must be per-note.

Scope

  • TS: importNotesFromProposals(midenClient, proposals, { midenRpcEndpoint }).
  • Rust: import_notes_from_proposals(&[Proposal]) on MultisigClient.
  • Per note: decode base64 → deserialize Note → check already-present/consumed → fetch inclusion proof → import individually as NoteWithProof (or NoteDetails/Expected for not-yet-committed) → outcome.
  • Per-note NoteImportOutcome { identifier, source: 'proposal', status: imported | already-present | already-consumed | not-committed | invalid | failed, retryable?, reason? }. A malformed note must not block the others.

Acceptance criteria

  • Both SDKs with semantic parity.
  • Tests: valid public, valid private (body from local bytes only), uncommitted (retryable, no abort), malformed (isolated failure), already-consumed classification.
  • Docs: proposals are opportunistic recovery material, not a backup (may be absent, stale, or deleted after canonicalization); embedded note bytes are visible to the Guardian operator — existing v2 behavior, not a new exposure.

Unblocked (spike complete).

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions