* fix(precompute): correct cache validation and path separator
- Fix cache file size validation rejecting valid files: use 1 byte/point
minimum bound instead of hardcoded 65 bytes, since infinity points are
serialized as 1 byte (flag only, no x/y coordinates). Addresses #116.
- Fix path separator: use '/' unconditionally instead of Windows backslash,
since forward slashes work on all platforms. Addresses #117.
* fix(ci): fuzz_point k=n-1 edge case, benchmark noise filter
- fuzz_point: handle k=n-1 where (k+1)*G = 0*G = infinity (pre-existing bug)
- parse_benchmark.py: add MIN_REGRESSION_NS=25.0 filter to skip sub-25ns
micro-ops that produce false positive regressions on shared CI runners
* fix(ci): use fixed -march=x86-64-v3 with ccache, widen benchmark threshold
- CMakeLists.txt: add SECP256K1_MARCH option to override -march=native
Prevents SIGILL when ccache restores objects from a different CI runner CPU
- All x86-64 workflows with ccache: pass -DSECP256K1_MARCH=x86-64-v3
- bench-regression.yml: increase alert-threshold from 150% to 200%
Shared CI runners show up to ~60% variance on micro-ops
* fix(ci): raise MIN_REGRESSION_NS to 50ns
field_mul (15.8ns baseline) inflated to 32.5ns on CI runner (2.06x),
exceeding even 200% threshold. Sub-50ns micro-ops are too granular
for shared runner regression detection. Still shown in Dashboard.
* add ABI layout guards and CRYPTO_INVARIANTS.md
- ufsecp.h: static_assert guards on struct sizes and constant lengths
to catch ABI-breaking changes at compile time (C++ and C11)
- docs/CRYPTO_INVARIANTS.md: comprehensive crypto invariant reference
covering private key validation, nonce safety (RFC 6979), pubkey
validation, signature encoding, hash domain separation, point
arithmetic, key tweaking, serialization byte order, thread safety,
and constant-time guarantees
---------
Co-authored-by: shrec <shrec@users.noreply.github.com>