Skip to content

Replace linear nonce-replay scan with a hashed set #7

Description

@iamonuwa

Context

The replay check in kanon-core/src/verify.rs:91-98 is a linear scan over ctx.seen_nonces, and normalize_hex allocates a fresh String for every element on every call. seen_nonces is Vec<String> (model.rs:93) with no cap and no dedup.

An external benchmark measured the cost. With the target nonce absent, verify degrades from ~187 us at an empty set to ~10.3 ms at 500k entries, roughly 55x the cost of the signature recovery itself. RSS grows to ~104 MB at 500k because every nonce is held as a raw hex String and re-allocated during the scan. The scan cost equals the crypto cost at around 10k entries.

This is invisible in CI because all nine corpus vectors carry empty replay sets. It also makes the verifier a CPU-exhaustion surface for any caller that passes an untrusted or unbounded consumed-nonce set. It never crashes, it just gets arbitrarily slow.

Proposed fix

  • Normalize each nonce once at Context / BareOptions construction (strip 0x, lowercase, decode to [u8; 32]) and store in a HashSet<[u8; 32]>.
  • The check becomes one normalize of the candidate plus one O(1) contains.
  • Reject nonces that do not decode to 32 bytes at construction, with a clear error, rather than silently never matching.
  • Document a recommended bound on the seen-nonces set at the CLI boundary.

Acceptance

  • Verify time is flat in seen-nonces set size.
  • A corpus or test vector exercises NONCE_REPLAY against a large seen-nonces set so the path is measured, not just asserted non-empty.
  • Python crosscheck unaffected. The wire format and reason codes do not change. This is internal to the verification context.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions