Skip to content

Add FFOR receiver lifecycle and receipt recovery on 0.2.5 - #4

Draft
coreyphillips wants to merge 22 commits into
0.2.5from
feat/ffor-channel-snapshot
Draft

coreyphillips wants to merge 22 commits into
0.2.5from
feat/ffor-channel-snapshot

Conversation

@coreyphillips

@coreyphillips coreyphillips commented Sep 20, 2026

Copy link
Copy Markdown

FFOR receiving needs the channel engine to retain real voucher claims while the receiver is offline. This draft ports the receiver lifecycle to rust-lightning v0.2.5 and adds one immutable, signed invoice assignment per supported epoch. It includes native persistence, witness acknowledgement and live-monitor checks before publication. It does not enable Bitkit's production provider or demonstrate an end-to-end offline payment.

Related to ldk-node #117 and ldk-node #118. Implementation and persistence contracts are documented in FFOR.md.

Receiver behavior

  • Reserve native recovery capacity and install the receiver interception gate before sending signed Init. The public facade binds the actual peer generation, retains exact request bytes and processes Accept synchronously before stock HTLC frames. Exact application intent can be recovered after disconnect or channel removal without allocating another epoch.
  • Authenticate setup against the actual node, chain, funding, balances, fees, reserves, dust and block-height limits. Verify both real anchor commitments and their claim signatures. Owned vouchers stay outside ordinary invoice, keysend and forwarding processing.
  • Use actual receiver-initiated STFU, frozen commitment proof and ordered manager persistence for activation. Signing runs outside native locks and every mutation revalidates ownership. Failed, delayed, cancelled or older writes cannot satisfy a newer persistence requirement.
  • Keep a durable mutation fence independent of transport quiescence. Ordinary adds, fees, splices and close paths remain blocked while the epoch is frozen. Reconnect retains stock commitment and revocation-secret checks, carries the FFOR report and requires the exact signed acknowledgement. An ambiguous Activate is never resent across a connection change.
  • Persist pre-active abort and cooperative close evidence before owned removal rounds. Known preimages reach stock monitor persistence before failures. Final Closed requires synchronized empty commitments and matching monitor proof, followed by another successful manager write before ordinary operation resumes.
  • Preserve immutable witness selection and exact manifests, with one through four witnesses. Native provisioning attempts are tied to the actual witness generation and become sent only after bounded enqueue succeeds. Only a correlated sent response can retain the first sufficient acknowledgement. Disconnect and restart invalidate transient attempts; restored authority requires fresh persistence.
  • Import authenticated encrypted witness receipts into the original channel monitor, including after channel removal. A late preimage cannot reverse an already committed failure. Receipt protection does not emit PaymentClaimed or receive credit.

Invoice assignment and publication

The supported issuer uses a one-slot, non-hash-chained Variant D book. It derives amount, payment hash, receiver identity, settlement fees, inbound alias and CLTV from native ownership. The signed Init witness restriction must exactly match the registered and durably acknowledged witness set.

The invoice has one W -> S -> R route hint and no MPP support. Native verifies the public W-S announcement and directional update, signatures, distinct identities, canonical endpoint ordering, enabled state, amount bounds, fees and freshness. These signatures identify route terms; they do not prove current channel funding or liquidity. Private W-S channels without authenticated route evidence are not supported. BOLT11 hints remain advisory, with the signed witness restriction providing the honest settlement peer's admission guard.

Signing occurs outside locks. Native then rechecks the current phase, frozen pair, deadline, route binding and completed persistence before retaining the exact signed bytes. Requested expiry is capped using eight minutes per remaining block before admission closes, less the explicit safety margin. The actual watched monitor is locked through retention or final bounded publication, excluding pending off-chain persistence, known preimages, funding spends, pending funding changes and local commitment signing. The higher of manager and monitor height is used so delayed notifications cannot extend admission.

The storage getter returns exact bytes only after the latest native write completes. It supports historical recovery after expiry or close and does not grant display permission. The application must first durably confirm these bytes, the matching Pending payment and its protected confirmation marker. Final publication rechecks native and monitor state through a callback that performs only bounded in-memory publication. Retry, failed publication and restart cannot replace the assigned invoice. Custom Watch implementations default to refusing this operation until they implement the actual-monitor boundary. New issuance requires the std clock; no_std supports historical decoding.

Cooperative outcome journal

A new drain initializes a versioned journal with resolved and fulfilled bits per book slot, at most 483 slots. The stock revoke-and-ack removal of an inbound LocalRemoved HTLC records the exact owned voucher's slot at the same point it adds a fulfilled amount to the balance, with no new fallible step after the existing preflight. The journal is native accounting only, never derived from the signed settled bitmap or known preimages, and fulfilled is always a subset of resolved. A preimage learned after a signed failure protects the monitor but leaves the slot failed.

Restore validation requires exact bitmap lengths, zero padding, the subset rule and, per slot, either a resolved bit or the voucher still pending as a stock HTLC. The completion proof requires every slot resolved and every signed settled slot fulfilled, binds the journal into a distinct v2 digest domain, and carries it into the retained ClosedDrain under required-even field 14 with archive version 8. Legacy drains and archives keep the original domain, remain readable and never acquire invented outcomes; older readers reject journaled records instead of dropping them. The framing growth of a journaled Closed proof is charged inside the existing 512-byte terminal reservation.

ffor_receiver_voucher_outcome is a historical, manager-instance-bound getter keyed by the current epoch context, one-based slot, exact payment hash and amount. It reports Fulfilled or Failed only from a fully finalized journal after the latest native write completed, including a fresh barrier after restore. Pending drains, force-closed epochs and legacy absence return no outcome. It changes no balances and emits no events. On-chain outcomes remain a separate unimplemented boundary.

Repeated epochs on one channel

A new epoch on a channel with an existing registration is admitted only when the previous epoch is terminal without ambiguity: its book has an authenticated setup, no fence and no pending pre-init gate, and its drain is Closed with the retained completion hash or it is aborted without a drain; no owned inbound HTLC, holding-cell claim, pending finalized fulfill, in-flight or blocked monitor update, quiescence, splice or interactive session remains; and under the archive lock the archived record for the previous epoch is terminal with the same completion hash or abort reason, its runtime persistence requirement is complete, and archive capacity admits another record. The new book names its predecessor epoch under a required-even field. Restore requires the archived terminal predecessor record and rejects two unresolved records sharing a channel or funding identity; a book naming itself is rejected. Previous epochs stay readable by epoch id, including outcomes and invoices, and a witness receipt for a replaced epoch still imports into the original monitor without payment events. Reuse after a setup aborted before activation or a request the peer never accepted remains refused because the archive holds no durable abort evidence for those.

Recovery bounds

Native history is bounded to 64 records and 8 MiB, with at most 512 KiB per record and terminal transition capacity reserved before admission. Required serialized fields prevent old readers from dropping FFOR state. Immutable witness metadata uses schema 5; the fixed 373-byte acknowledgement field uses schema 6. Invoice assignment adds required field 12 and schema 7, bounding the signed string to 4096 bytes and its record to 8192 bytes. Local archive validation is not an authenticated storage envelope or rollback detector. The companion unpublished lightning-ffor crate supplies shared canonical protocol and witness verification.

Validation

  • All 179 focused native FFOR tests pass, including 13 invoice tests, the cooperative outcome journal checks, the repeated-epoch checks and both channel funding roles. The full lightning library suite also passes on this checkpoint.
  • Invoice coverage includes every durable witness acknowledgement, exact retries, failed and stale persistence, restored handles, wrong signers, signed route loops, missing or additional witness permissions, archive corruption and capacity, monitor height ahead of manager, known preimages without a counter change, funding spend before manager notification, and actual monitor exclusion through publication.
  • A genuine public-driver fixture covers setup through witness registration and invoice assignment. It exposed and now guards a runtime/height lock inversion in witness registration and release. The affected paths use a consistent registry, runtime, height and persistence order.
  • Existing FFOR coverage exercises activation, reconnect, abort, close, historical request recovery, witness correlation and original-monitor receipt protection. The invoice checkpoint adds no ordinary payment credit.
  • Repeated-epoch coverage runs two full cooperative epochs on one channel for both funders with ordinary payments between them and both journals readable before and after reload; refuses reuse while the previous epoch is Activating, Active, close-acknowledged but unpersisted, Draining, drained without proof, or Closed pending its final write; admits it after release with idempotent retry; refuses while Aborting and permits after an aborted drain; refuses when archive capacity is exhausted; rejects a restored later epoch without the terminal predecessor record and an archive with two unresolved records for one channel; and imports a previous epoch's witness receipt into the original monitor after reuse.
  • Journal coverage extends the cooperative drain matrix across both funders, signed settled, learned and failed slots, delayed monitors and restart mid-round: outcomes absent before the retained Closed proof, exact afterwards, refused for wrong slots, hashes and amounts, absent on a restored manager until its fresh write, and preserved as archive-only history after the channel is force-closed away. A late receipt after a signed failure reports Failed and a force-closed drain reports nothing. Archive tests cover the legacy digest, journaled round trips at the maximum 483-slot book inside the terminal reservation, replacement refusal, old readers, version bytes and malformed journals. Drain tests cover legacy records restoring without a journal and closed drains freezing theirs.
  • The no-default-features check of the lightning crate passes with only pre-existing warnings.
  • Documentation builds with broken intra-doc links denied.
  • rustfmt reports no changes in the touched FFOR modules; the remaining repo-wide rustfmt differences predate this branch.

Remaining work

Joining journaled outcomes to the application payment ledger, on-chain outcomes, production Node scheduling and bindings, private witness route support, settlement interoperability and process-stopped mobile payment tests remain incomplete. Reuse after a pre-activation abort still needs durable abort evidence in the archive. Application persistence remains a required part of the publication contract. Deployment margins and witness coverage need explicit policy. This PR remains a draft.

@coreyphillips coreyphillips changed the title Add FFOR committed voucher verification on 0.2.5 Add FFOR receiver voucher parking on 0.2.5 Sep 20, 2026
@coreyphillips coreyphillips changed the title Add FFOR receiver voucher parking on 0.2.5 Add FFOR receiver parking and shared protocol on 0.2.5 Sep 21, 2026
@coreyphillips coreyphillips changed the title Add FFOR receiver parking and shared protocol on 0.2.5 Add authenticated FFOR receiver setup and recovery on 0.2.5 Sep 21, 2026
@coreyphillips coreyphillips changed the title Add authenticated FFOR receiver setup and recovery on 0.2.5 Add FFOR receiver setup, quiescence and witness provisioning on 0.2.5 Sep 21, 2026
@coreyphillips coreyphillips changed the title Add FFOR receiver setup, quiescence and witness provisioning on 0.2.5 Add FFOR receiver setup, activation evidence and channel guards on 0.2.5 Sep 21, 2026
@coreyphillips coreyphillips changed the title Add FFOR receiver setup, activation evidence and channel guards on 0.2.5 Add FFOR receiver activation and reconnect recovery on 0.2.5 Sep 21, 2026
@coreyphillips coreyphillips changed the title Add FFOR receiver activation and reconnect recovery on 0.2.5 Add FFOR receiver activation, close recovery and witness decryption on 0.2.5 Sep 21, 2026
@coreyphillips coreyphillips changed the title Add FFOR receiver activation, close recovery and witness decryption on 0.2.5 Add FFOR receiver setup, activation and recovery on 0.2.5 Sep 21, 2026
@coreyphillips coreyphillips changed the title Add FFOR receiver setup, activation and recovery on 0.2.5 Add FFOR receiver lifecycle and recovery on 0.2.5 Sep 21, 2026
@coreyphillips coreyphillips changed the title Add FFOR receiver lifecycle and recovery on 0.2.5 Add FFOR receiver lifecycle and witness registration on 0.2.5 Sep 21, 2026
@coreyphillips coreyphillips changed the title Add FFOR receiver lifecycle and witness registration on 0.2.5 Add FFOR receiver lifecycle and receipt recovery on 0.2.5 Sep 21, 2026
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