Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
secp256k1: Optimize k splitting with mod n scalar.
This optimizes the scalar decomposition code by rewriting it to make use of the highly-efficient zero-allocation ModNScalar type along with math/bits (which provides hardware acceleration on most platforms) instead of big.Ints. The net effect is that the decomposition is significantly faster, allocation free, and constant time. It also adds a bunch of detailed comments to better describe the endomorphism and how it is used in scalar multiplication in addition to fully describing the scalar decomposition process and derivation. Finally, it adds logic to derive and print the new constants the reworked code makes of to the precomputation code that runs with 'go generate'. The following is a high level overview of the changes: - Rewrites splitK to use the ModNScalar type instead of big.Ints: - Allocation free - Constant time - Provides hardware acceleration on most platforms - Includes detailed comments describing the scalar decomposition process and derivation - Updates endomorphism parameter constant definitions to be ModNScalars instead of big.Int - Moves the convenience func hexToModNScalar to the main package - Adds new endoZ1 and endoZ2 constants for the rounded multiplication used by the new decomposition code - Adds logic to derive and print the new endomorphism constants with 'go generate' - Updates the scalar multiplication to account for the new semantics - Adds detailed comments to scalar multiplication - Tightens negation magnitudes in addZ1EqualsZ2 and remove no longer needed normalization - Ensures the calculation when recovering compact signatures uses normalized points - Updates associated tests - Updates associated benchmark - Removes splitKModN test helper since conversion is no longer needed The following benchmarks show a before and after comparison of scalar decomposition as well as how it that translates to scalar multiplication and signature verification: name old time/op new time/op delta --------------------------------------------------------------------- SplitK 1.61µs ±32% 0.89µs ± 2% -44.69% (p=0.000 n=50+47) ScalarMult 125µs ± 1% 115µs ± 1% -7.82% (p=0.000 n=43+46) SigVerify 161µs ±25% 160µs ±19% -0.53% (p=0.001 n=50+50) name old allocs/op new allocs/op delta ----------------------------------------------------------------------- SplitK 10.0 ± 0% 0.0 -100.00% (p=0.000 n=50+50) ScalarMult 11.0 ± 0% 0.0 -100.00% (p=0.000 n=50+50) SigVerify 28.0 ± 0% 16.0 ± 0% -42.86% (p=0.000 n=50+50) While it only saves about 1 µs per signature verification in the benchmarking scenario, the primary win is the reduction in the number of allocations per signature verification which has a much more significant impact when verifying large numbers of signatures back to back, such as when processing new blocks, and especially during the initial chain sync process.
- Loading branch information