Skip to content

Speed up signing - #61

Open
anudit wants to merge 1 commit into
leanEthereum:mainfrom
anudit:main
Open

anudit wants to merge 1 commit into
leanEthereum:mainfrom
anudit:main

Conversation

@anudit

@anudit anudit commented Oct 1, 2026

Copy link
Copy Markdown

Optimizes the ordinary SignatureScheme::sign path. The public API, key and signature formats, and signature bytes are unchanged (the same seed and message produce the same signature).

  • Cached Poseidon permutations: poseidon1_16() / poseidon1_24() now return &'static instead of cloning heap-backed round constants on every hash.
  • Encoding search:
    • New IncomparableEncoding::find_encoding hook; its default keeps the original loop.
    • Target-sum/Poseidon prepares the message and epoch inputs once, then hashes retries in SIMD batches.
    • For w=8, searches run in bounded parallel windows that keep the lowest successful counter and the original MAX_TRIES limit.
  • Chunk decoding: power-of-two bases are decoded from fixed u64 limbs with shift/mask instead of BigUint division.
  • PRF: new Pseudorandom::randomness_generator reuses the SHAKE prefix across counters, and field reduction no longer uses generic u128 division.
  • Chain walking: TweakableHash::sign_chains groups chains of similar length into SIMD lanes, then restores the signature order.
  • Tweaks: tweak encoding uses u64 arithmetic instead of u128.
  • Benchmark: signing keys now activate only the two bottom trees needed (the tree height stays the same), and verification fixtures are built lazily outside the timed loop. Setup no longer dominates runs or profiles.

Benchmarks

Criterion, Lifetime 2^18, no offset, Apple M2 Max, rustc 1.96.0. Both columns use the same harness; "before" is c08a3ba.

Single core (RAYON_NUM_THREADS=1)

Signing:

w Before After Speedup
1 595 µs 159 µs 3.8×
2 773 µs 153 µs 5.0×
4 1.44 ms 295 µs 4.9×
8 12.88 ms 2.51 ms 5.1×

Verification:

w Before After Speedup
1 532 µs 413 µs 1.3×
2 502 µs 349 µs 1.4×
4 849 µs 517 µs 1.6×
8 6.05 ms 3.41 ms 1.8×

8 threads (RAYON_NUM_THREADS=8)

w Sign before Sign after Speedup
1 466 µs 132 µs 3.5×
2 459 µs 139 µs 3.3×
4 923 µs 227 µs 4.1×
8 7.82 ms 856 µs 9.1×

Verification also improves because it shares the permutation and tweak paths.

Reproduce:

RAYON_NUM_THREADS=1 cargo bench --bench benchmark -- 'Lifetime 2\^18, w = [1248], no offset' --warm-up-time 1 --measurement-time 3

Testing

  • cargo test --release: 117 passed, 1 ignored (slow).
  • cargo clippy --all-targets --release -- -D warnings and cargo fmt --check are clean.
  • New tests:
    • A fingerprint test checks that w=8 signatures are byte-identical to the pre-optimization implementation.
    • Fixed-limb decoding is checked against BigUint.
    • The batched search is checked against scalar counter order and the retry limit.
    • SIMD chains are checked against scalar chains, including 0/255 steps and partial groups.
    • PRF reduction is checked against the scalar version.

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