Skip to content

reuse: serve the previous v5/v6 signature while the price is unchanged and unexpired - #72

Merged
kaisbaccour merged 1 commit into
feat/signature-cachefrom
feat/signature-reuse
Sep 2, 2026
Merged

reuse: serve the previous v5/v6 signature while the price is unchanged and unexpired#72
kaisbaccour merged 1 commit into
feat/signature-cachefrom
feat/signature-reuse

Conversation

@kaisbaccour

@kaisbaccour kaisbaccour commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #71 (content cache within a frame). This one works across frames.

Problem

Pricing publishes a frame per symbol every ~5s. Even after #71, an unchanged price gets a new signature on every frame, because publish_time and expiry move with the frame and are signed. For a stable symbol that is 12 signatures a minute saying the same price.

Change

For v5 and v6 the handler keeps the last response per (schema, symbol, direction) with a fingerprint of everything signed except the two timestamps: price bytes, session tag and bounds, input and output token, and the v6 NAV ratio. A new frame with the same fingerprint, while the previous quote still has at least signing.reuse_min_remaining_secs (default 10) before its expiry, gets the previous response back unchanged. The taker reads the older publish time and the original expiry in the signed bytes and judges freshness itself.

  • A moving price, a session change or a NAV change always signs fresh.
  • v1 and v4 never reuse: no expiry in their bytes, and the strategy's on-chain staleness rule is not visible here.
  • [signing] reuse_min_remaining_secs = 0 in the runtime TOML disables it. The t0.devops config-as-data file needs no change for the default.
  • oracle_signature_reuse_total on /metrics counts the KMS calls avoided.

Effect

Expiry is stamped 20 to 30s after the frame today, so a stable pair costs one signature per ~20s instead of one per 5s frame, roughly a further 4x on quiet symbols and nothing on fast movers. Combined with #71 the KMS bill follows how often prices actually change, not how often anyone asks.

Tests

Five integration tests using a new LiveClient::seed helper to push frames between requests: reuse on unchanged price, no reuse under the expiry margin, v4 always fresh, disabled setting signs every frame, v6 requires the same NAV ratio. cargo test 103 passed, clippy and fmt clean.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

…d and unexpired

The content cache (previous commit) removes duplicate signatures inside
one price frame. A new frame every 5 seconds still meant a new signature
per pair even when the price had not moved, because publish_time and
expiry advance with the frame and are part of the signed bytes.

This layer works across frames. For v5 and v6 the handler remembers the
last response per (schema, symbol, direction) together with a
fingerprint of everything signed except the two timestamps: price bytes,
session tag and bounds, input and output token, and for v6 the NAV
ratio. When a new frame arrives with the same fingerprint and the
previous quote still has at least signing.reuse_min_remaining_secs
(default 10) before its expiry, the previous response is returned as is.
The taker sees the older publish_time and the original expiry in the
signed bytes and judges freshness itself. A moving price, a session
change or a NAV change always signs fresh.

v1 and v4 never reuse: they sign no expiry, and the strategy's staleness
rule on chain is not visible here.

Pricing stamps expiry 20 to 30 seconds after the frame today, so a
stable symbol now costs one signature per ~20s instead of one per 5s
frame. Set reuse_min_remaining_secs = 0 in the [signing] table to sign
every frame. oracle_signature_reuse_total counts the KMS calls avoided.

LiveClient::seed lets the integration tests push new frames between
requests; five new tests cover reuse, the expiry margin, v4 exclusion,
the disabled setting and the v6 NAV ratio.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@kaisbaccour

Copy link
Copy Markdown
Collaborator Author

Folded into #71 at Kais's request; same commits, one PR.

@kaisbaccour
kaisbaccour merged commit 74d3cd6 into feat/signature-cache Sep 2, 2026
3 checks passed
@kaisbaccour
kaisbaccour deleted the feat/signature-reuse branch September 2, 2026 10:01
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