Skip to content

Refresh cached OHTTP keys sooner and on session build failure - #77

Open
chavic wants to merge 2 commits into
ValeraFinebits:masterfrom
chavic:chavic/ohttp-key-cache-refresh
Open

Refresh cached OHTTP keys sooner and on session build failure#77
chavic wants to merge 2 commits into
ValeraFinebits:masterfrom
chavic:chavic/ohttp-key-cache-refresh

Conversation

@chavic

@chavic chavic commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Directory OHTTP keys can rotate, and the 12-hour cache had no refresh path: after a rotation, every new session build against the stale keys fails and checkout silently falls back to plain BIP21 until the cache window lapses.

Two small changes bound that window:

  • the cache lifetime drops to one hour;
  • a session build failing with a library error invalidates the cached keys for that relay/store, so the very next payment-URL request refetches instead of waiting the window out. The cost of an unnecessary invalidation is one extra keys fetch.

Existing sessions are unaffected either way — their OHTTP key material is baked into the persisted session context at build time, which is also why creation time is the only useful refresh hook.

🤖 Generated with Claude Code

@chavic
chavic force-pushed the chavic/ohttp-key-cache-refresh branch from b4b3668 to 1db06f6 Compare July 6, 2026 15:31
@chavic
chavic force-pushed the chavic/ohttp-key-cache-refresh branch from 1db06f6 to 6f9629e Compare July 16, 2026 10:46
@chavic
chavic marked this pull request as ready for review July 16, 2026 12:48
@ValeraFinebits
ValeraFinebits self-requested a review July 18, 2026 20:20

@ValeraFinebits ValeraFinebits left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing stale OHTTP keys. Reducing the TTL to one hour does bound the stale-key window, but I don’t think it, together with invalidation around InitializeSession, addresses the underlying lifecycle issue. A stale but structurally valid key should still initialize locally and only be rejected when communicating with the directory, for example through an OHTTP-key HTTP 422 response.

The server-side design being developed in rust-payjoin #1449, and the review direction around #1035, point toward directory-controlled freshness through Cache-Control metadata (currently s-maxage) plus a rotation overlap/grace period. Since the keys belong to the directory rather than the relay, the client should use the remaining freshness lifetime returned with the currently advertised key, not start a new fixed three-month or one-hour TTL when the plugin fetches it.

Could we either keep fetching keys for each new session until this metadata is exposed through the API/FFI, or follow that contract once it becomes available? If a specific OHTTP-key 422 is exposed through the FFI.

chavic added 2 commits July 28, 2026 16:06
Move the submodule from f4a6008a to the payjoin-1.0.0-rc.6 release
commit and adapt to the FFI surface changes:

- PjParseException is now UriParseException.
- BuildRecommended throws SenderInputException, and persisted sender
  errors are now SenderPersistedException.Transient/Fatal wrapping a
  SenderException, so the receiver-rejection handling matches
  SenderException.Response through the wrapper.
- IPayjoinProposal drops UtxosToBeLocked and gains
  ProposalTxidIsStable.

rc.5-format closed-session logs recorded scripts and witnesses in
Closed(Success); rc.6 records a txid, so such logs fail replay after
this bump. Every replay site already catches ReceiverReplayException
and removes the session, which is the same terminal outcome a closed
session gets on the next poller tick.
Directory OHTTP keys can rotate, and the twelve-hour cache had no
refresh path: after a rotation every new session build failed until the
window lapsed, falling back to plain BIP21 the whole time. The cache
lifetime is now one hour, and a session build failing with a library
error drops the cached keys for that relay and store so the next attempt
starts from freshly fetched material. Existing sessions are unaffected
either way since their keys are baked into the session context.
@chavic
chavic force-pushed the chavic/ohttp-key-cache-refresh branch from 6f9629e to 455c260 Compare July 29, 2026 08:43
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.

2 participants