perf(precompiles): dedupe secp256k1 work in the ECIES path - #1385
Closed
mattsse wants to merge 1 commit into
Closed
Conversation
Chaum-Pedersen verification evaluated `R1 = s*G - c*pubSeq` and `R2 = s*ephemeralPub - c*sharedSecret` as four independent scalar multiplications, and re-derived the generator's 65-byte SEC1 encoding on every challenge hash. On the prover side each deposit recomputed `privSeq * G`, which depends only on the key, and the deterministic authenticated-withdrawal path computed `eph * G` twice per withdrawal. Both verification equations are now single two-term linear combinations evaluated with k256's `lincomb` (Straus with the GLV endomorphism, the routine its own ECDSA verification uses), the generator encoding is a constant pinned by a test, and generator multiplications go through `mul_by_generator` so they use k256's precomputed basepoint tables where that feature is resolved on, which it is for the node binary. `PreparedDecryptionKey` derives the sequencer public point once so a caller decrypting several deposits under one key stops repeating it; `compute_ecdh_proof` and `decrypt_deposit` remain as thin wrappers, so callers outside the crate are unchanged. Adopting the prepared key in the L1 deposit loop is left as a follow-up. Every output stays byte-identical. The Chaum-Pedersen proof scalars and the deterministic authenticated-withdrawal ciphertext are now pinned by fixed-vector assertions whose expected values were captured from main. Measured with a throwaway in-crate A/B harness (release profile, old and new alternating in small chunks, minimum per chunk, k256 features matching the node binary): ChaumPedersenVerify::verify 172 us -> 137 us challenge_hash 5.6 us -> 0.7 us compute_ecdh_proof 173 us -> 132 us compute_ecdh_proof, key reused 173 us -> 110 us decrypt_deposit 177 us -> 136 us decrypt_deposit, key reused 177 us -> 114 us encrypt_authenticated_withdrawal_deterministic 134 us -> 76 us
mattsse
requested review from
0xKitsune,
0xrusowsky,
klkvr and
legion2002
as code owners
September 3, 2026 20:40
Contributor
Author
|
not worth it |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Chaum-Pedersen verification computed
s*G - c*pubSeqands*ephemeralPub - c*sharedSecretas four separate scalar multiplications and re-encoded the generator on every challenge hash. The ECIES side recomputedprivSeq * Gper deposit andeph * Gtwice per authenticated withdrawal.Each verification equation is now one two-term
lincomb(Straus with the GLV endomorphism, the routine k256 uses for its own ECDSA verify), the generator encoding is a constant pinned by a test, and generator multiplications usemul_by_generatorso they hit k256's precomputed tables where that feature is enabled, as it is for the node binary. A newPreparedDecryptionKeyderives the sequencer public point once per key;compute_ecdh_proofanddecrypt_depositremain as thin wrappers. Adopting it in the L1 deposit loop is a follow-up.All outputs are byte-identical, and the proof scalars and the deterministic withdrawal ciphertext are now pinned by fixed vectors captured from main. Measured with a throwaway interleaved A/B harness on the release profile:
verify172 → 137 µs,challenge_hash5.6 → 0.7 µs,compute_ecdh_proof173 → 132 µs (110 µs with a reused key),decrypt_deposit177 → 136 µs (114 µs reused),encrypt_authenticated_withdrawal_deterministic134 → 76 µs.