Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

secp256k1: Optimize k splitting with mod n scalar. #2888

Merged
merged 4 commits into from
Mar 14, 2022

Commits on Mar 14, 2022

  1. secp256k1: Rework k splitting tests.

    This reworks the k (scalar) splitting tests to make them more consistent
    with modern practices in the code as well as to make the testing
    methodology less reliant on the specific implementation details and to
    test edge cases.
    
    It also updates the random k splitting tests to ensure new random values
    are tested each run as opposed to the existing tests which always test
    the same values since they use the same random seed.
    
    Specifically, the following properties are asserted:
    
    - The decomposed scalars must result in the original scalar via the
      equation k = k1 + k2*lambda (mod n)
    - Both decomposed scalars must have small magnitude as determined by
      having a maximum bit length of one more than half of the bit size of
      the underlying field
    davecgh committed Mar 14, 2022
    Configuration menu
    Copy the full SHA
    ecb2281 View commit details
    Browse the repository at this point in the history
  2. secp256k1: Generate all endomorphism params.

    This modifies the code related to precomputing the linearly independent
    vectors used by the endomorphism to compute all of the related params,
    including lambda and beta, as well as the alternative params.  It also
    ensures the derived values satisfy the required equations.
    
    This helps makes it clear how they are derived as opposed to being
    magical constants and also makes it easier to include new derived values
    which are planned for an upcoming optimization.
    davecgh committed Mar 14, 2022
    Configuration menu
    Copy the full SHA
    0579adb View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    b4c4535 View commit details
    Browse the repository at this point in the history
  4. 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.
    davecgh committed Mar 14, 2022
    Configuration menu
    Copy the full SHA
    7833beb View commit details
    Browse the repository at this point in the history