Skip to content

Conversation

@setavenger
Copy link

This change reduces the time needed to generate pubkeys from tweaks by ~9% (see benchmarks [here]).(https://github.com/setavenger/libsecp256k1-sp-example/blob/optimise_sp_module/bench_results/bench-optimised-module-100-iter.txt)

In concrete numbers from my machine:

The setup were 10 runs with 100 iterations each. One iteration generated pub keys from 861 tweaks (tweaks were taken from block 834761).

Optimised Implementation:
Mean: 34.9741 seconds
Median: 34.9358 seconds
Standard Deviation: 0.4609 seconds

Base Implementation:
Mean: 38.7348 seconds
Median: 38.5146 seconds
Standard Deviation: 0.9978 seconds

jonasnick and others added 14 commits March 18, 2024 16:50
Add function for calculating either a*B or A*b. This function is used by both
the sender and the recipient (i.e. a*B == A*b).

add input hash func
Given a set of private keys, the smallest outpoint, and list of recipients this
function handles the entire sender flow:

1. Sum up the private keys
2. Calculate the input_hash
3. For each recipient:
    3a. Calculate a shared secret
    3b. Create the requested number of outputs

This function assumes a single sender context in that it requires the
sender to have access to all of the private keys. In the future, this
API may be expanded to allow for a multiple senders or for a single
sender who does not have access to all private keys at any given time,
but for now these modes are considered out of scope / unsafe.
The vectors are generated with a Python script that converts the .json
file from the BIP to C code:

$ ./tools/tests_silentpayments_generate.py test_vectors.json > ./src/modules/silentpayments/vectors.h
Comment on lines 119 to 122
if (!secp256k1_ecdh(ctx, shared_secret33, public_component, tweaked_secret_component, secp256k1_silentpayments_ecdh_return_pubkey, NULL)) {
if (!secp256k1_ec_pubkey_tweak_mul(ctx, &ecdhSecretPubKey, tweaked_secret_component)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because secp256k1_ecdh is constant time, whereas ec_pubkey_tweak_mul is not. Its something we've been discussing, whether its safe / worth it to use ec_mult instead of forcing it to be constant time, but its nice to see some actual numbers! I'm a bit surprised the speedup is only 7%ish; an earlier comment indicated it might be up to 25% improvement (per https://gist.github.com/RubenSomsen/c43b79517e7cb701ebf77eec6dbb46b8?permalink_comment_id=4125475#gistcomment-4125475)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh yeah that makes sense, I wasn't sure about that. With regards to the speed up, the number in the title is wrong it's more ~9%. I'm also not sure where exactly the 25% come from but I do a general benchmark on creating pub keys not just computing the secret. It's possible that when we run a benchmark exclusively on the shared secret, that we'll see a bigger percentage difference between implementations.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran similar benchmarks isolating the ecdh computation. I find a ~19% time reduction when using simple multiplication instead of constant time ecdh.

@setavenger setavenger changed the title according to benchmarks speed up by about 7-8% for pubkey computation according to benchmarks speed up by about ~9% for pubkey computation Apr 9, 2024
@josibake josibake force-pushed the bip352-api-refactor branch 7 times, most recently from a8d8a86 to 3998773 Compare April 17, 2024 14:42
josibake pushed a commit that referenced this pull request Nov 14, 2024
… names

87384f5 cmake, test: Add `secp256k1_` prefix to test names (Hennadii Stepanov)

Pull request description:

  This PR improves regex matching options when using `ctest` in downstream projects, such as Bitcoin Core.

  For instance, a downstream project users can filter their tests like that:
  ```
  ctest --tests-regex "secp256k1"
  ```
  or
  ```
  ctest --exclude-regex "secp256k1"
  ```

  A `ctest` log with this PR:
  ```
  $ ctest --test-dir build -j 16
  Internal ctest changing into directory: /home/hebasto/git/secp256k1/secp256k1/build
  Test project /home/hebasto/git/secp256k1/secp256k1/build
      Start 1: secp256k1_noverify_tests
      Start 2: secp256k1_tests
      Start 3: secp256k1_exhaustive_tests
      Start 4: secp256k1_ecdsa_example
      Start 5: secp256k1_ecdh_example
      Start 6: secp256k1_schnorr_example
      Start 7: secp256k1_ellswift_example
      Start 8: secp256k1_musig_example
  1/8 Test bitcoin-core#4: secp256k1_ecdsa_example ..........   Passed    0.00 sec
  2/8 Test bitcoin-core#5: secp256k1_ecdh_example ...........   Passed    0.00 sec
  3/8 Test bitcoin-core#6: secp256k1_schnorr_example ........   Passed    0.00 sec
  4/8 Test bitcoin-core#7: secp256k1_ellswift_example .......   Passed    0.00 sec
  5/8 Test bitcoin-core#8: secp256k1_musig_example ..........   Passed    0.00 sec
  6/8 Test bitcoin-core#3: secp256k1_exhaustive_tests .......   Passed    6.19 sec
  7/8 Test #1: secp256k1_noverify_tests .........   Passed   38.83 sec
  8/8 Test #2: secp256k1_tests ..................   Passed   91.66 sec

  100% tests passed, 0 tests failed out of 8

  Total Test time (real) =  91.67 sec
  ```

ACKs for top commit:
  theuni:
    utACK 87384f5
  real-or-random:
    utACK 87384f5

Tree-SHA512: d8e46558cf58c9c660544b7bdfed24c991eb3e120b6511aa3968f509190130e498749a3c4dbabc87a7f22f0aa0056c6bcd3fc6c44f5eb131588945d593546840
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.

4 participants