Skip to content

draft(wallet): batched NUT-07 pre-flight for Send/TokenCreated sagas — context sketch for the startup-recovery cost (#2631) - #2632

Draft
Amperstrand wants to merge 1 commit into
cashubtc:mainfrom
Amperstrand:batch-spent-send-recovery
Draft

Amperstrand wants to merge 1 commit into
cashubtc:mainfrom
Amperstrand:batch-spent-send-recovery

Conversation

@Amperstrand

Copy link
Copy Markdown

Draft — raised to showcase a problem, not to propose a final design.
The cost profile, measurements, and discussion live in #2631. This
branch exists so the maintainers can see one possible batching
shape against the real code — treat it as context for exploring the
problem, not a change ready for review. Closing it is fine if the
conclusion is a different shape.

What this sketch shows

A pre-flight inside recover_incomplete_sagas that:

  • collects Send/TokenCreated candidates and their reserved proofs,
  • asks the mint about all of them in chunked batch NUT-07 requests
    (256 proofs per request in the sketch — one round-trip where the
    sequential loop would make 256),
  • for each saga whose proofs are ALL spent, applies the same
    spent-branch bookkeeping recover_or_complete_send applies (proofs
    Spent, transaction Pending → Completed, row deleted),
  • defers everything else — unspent rows (revoke window), other saga
    kinds, and the whole chunk on any request failure — untouched to the
    existing sequential resume paths, so offline/flaky mints see no
    behavior change.

Deliberately open questions (why this is a draft)

  • Where this belongs: inside recovery at all, vs. a runtime/periodic
    pass, vs. both. Our production daemon chose the periodic pass; this
    sketch puts it in recovery because that's where every wallet pays the
    cost today.
  • Chunk sizing: 256 proofs/request is a placeholder.
  • Interaction with refactor(wallet)!: unify resumable Rust and FFI workflows #2479: that refactor reshapes the recovery loop
    (per-saga locking, re-fetch). This pre-flight is structurally
    independent of the loop's shape, but would need to be re-expressed on
    top of it — hence sketching now rather than proposing.
  • The SQL side: get_incomplete_sagas still returns every row; a
    state/kind filter might be the better or additional fix. We did not
    touch it here because that changes the primitive's contract for other
    callers.

Evidence the shape is viable

  • cargo test -p cdk --lib: 730 passed / 0 failed (3 new tests: batch
    finalization, unspent rows retained, unreachable-mint deferral).
  • One pre-existing test switched to a new additive mock helper
    (MockMintConnector::set_check_state_response_persistent) because the
    one-shot staged response is consumed by the batch call while the
    sequential path legitimately asks again.
  • Clippy clean.

Feedback very welcome — especially "wrong place, here's the right one".

…recovery

Draft raised to showcase a wallet-side recovery cost: one sequential
NUT-07 round-trip per accumulated saga row at every startup. Details,
measurements, and discussion in the linked issue. This shape is a
sketch for context, not a proposed final design.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

2 participants