add DLEQ proof based on BIP374 and use it for silent payments #1651

pull stratospher wants to merge 16 commits into bitcoin-core:master from stratospher:dleq-sp changing 23 files +10486 −12
  1. stratospher commented at 5:32 pm on February 3, 2025: contributor

    built on top of f42e0dde59943ad0c9247c61f7af521b70838e8f.

    BIP352 requires senders to compute output scripts using ECDH shared secrets from the same secret keys used to sign the inputs. Generating an incorrect signature will produce an invalid transaction that will be rejected by consensus. An incorrectly generated output script can still be consensus-valid, meaning funds may be lost if it gets broadcast. By producing a DLEQ proof for the generated ECDH shared secrets, the signing entity can prove to other entities that the output scripts have been generated correctly without revealing the private keys.

    (from BIP 374)

    This PR:

    • adds support for DLEQ proof generation and verification using secp256k1_dleq_prove, secp256k1_dleq_verify based on implementation in secp256k1-zkp
    • introduces a new structure for storing proofs in silent payment module - secp256k1_silentpayments_dleq_data which stores the shared secret computed using ECDH, DLEQ proof and also the index of which recipient in the original unsorted recipient array the proof refers to.
    • adds 4 new APIs in silent payments module to create, verify, serialize and parse proof
      1. sender can create proof using secp256k1_silentpayments_sender_create_outputs_with_proof
        • in the existing secp256k1_silentpayments_sender_create_outputs API, output pubkey is created by iterating over all the recipients and computing ECDH for each unique recipient.
        • since creating the proof also requites iterating over all recipients and computing ECDH for each unique recipient, compute both proof(s) and output pubkey(s) in a new function - secp256k1_silentpayments_sender_create_outputs_with_proof.
        • secp256k1_silentpayments_sender_create_outputs can use secp256k1_silentpayments_sender_create_outputs_with_proofinternally.
      2. both sender and receiver can verify proof using secp256k1_silentpayments_verify_proof
      3. Serialisation function (secp256k1_silentpayments_dleq_data_serialize) serialises secp256k1_silentpayments_dleq_data structure into bytes. secp256k1_silentpayments_dleq_data_parse parses the bytes back into secp256k1_silentpayments_dleq_data structure.
        1. useful if proof creation is done on 1 sender side device (ex: hardware wallet) and proof verification is done on another sender side device (ex: software wallet). secp256k1_silentpayments_dleq_data structure can be serialised into bytes using secp256k1_silentpayments_dleq_data_serialize and then the bytes can be sent from 1 device to another.
        2. secp256k1_silentpayments_dleq_data_parse can reconstruct the bytes back into secp256k1_silentpayments_dleq_data structure which can then be used for proof verification.

    open questions:

    1. is the API design ok?
      1. see examples/silentpayments.c for 2 scenarios in which proof verification could be useful. (Alice sends bitcoins to Bob and Carol in 1 silent payment transaction)
        1. useful situation - On Alice’s side
          1. Alice’s hardware wallet creates proof
          2. Alice’s hardware wallet sends proof to Alice’s software wallet
          3. Alice’s software wallet verifies proof and makes sure ECDH shared secrets for generating SP output is computed correctly. Alice can get additional safety guarantee about computed SP output before sending funds.
        2. not sure if this situation is useful - On Bob’s/Carol’s side
          1. Alice’s software wallet sends proof to Bob’s/Carol’s software wallet
          2. Bob’s/Carol’s software wallet verifies proof and makes sure ECDH shared secrets for generating SP output is computed correctly.
    2. should this be shipped with SP module or separately? only problem with separate release would be redundant APIs like secp256k1_silentpayments_sender_create_outputs and secp256k1_silentpayments_sender_create_outputs_with_proof for backward compatibility.

    Huge thanks to @ theStack for brainstorming and discussing this with me! ❤️

  2. build: add skeleton for new silentpayments (BIP352) module aa65f48aa2
  3. silentpayments: sending
    Add a routine for the entire sending flow which takes a set of private keys,
    the smallest outpoint, and list of recipients and returns a list of
    x-only public keys by performing the following steps:
    
    1. Sum up the private keys
    2. Calculate the input_hash
    3. For each recipient group:
        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.
    
    Internal to the library, add:
    
    1. A function for creating shared secrets (i.e., a*B or b*A)
    2. A function for generating the "SharedSecret" tagged hash
    3. A function for creating a single output public key
    
    Finally, add tests for the sender API.
    c546258b25
  4. silentpayments: recipient label support
    Add function for creating a label tweak. This requires a tagged hash
    function for labels. This function is used by the receiver for creating
    labels to be used for a) creating labelled addresses and b) to populate
    a labels cache when scanning.
    
    Add function for creating a labelled spend pubkey. This involves taking
    a label tweak, turning it into a public key and adding it to the spend
    public key. This function is used by the receiver to create a labelled
    silent payment address.
    
    Add tests for the label API.
    abe8c5aa6c
  5. silentpayments: receiving
    Add routine for scanning a transaction and returning the necessary
    spending data for any found outputs. This function works with labels via
    a lookup callback and requires access to the transaction outputs.
    Requiring access to the transaction outputs is not suitable for light
    clients, but light client support is enabled by exposing the
    `_create_shared_secret` and `_create_output_pubkey` functions in the
    API. This means the light client will need to manage their own scanning
    state, so wherever possible it is preferrable to use the
    `_recipient_scan_ouputs` function.
    
    Add an opaque data type for passing around the summed input public key (A_sum)
    and the input hash tweak (input_hash). This data is passed to the scanner
    before the ECDH step as two separate elements so that the scanner can
    multiply b_scan * input_hash before doing ECDH.
    
    Add functions for deserializing / serializing a public_data object to
    and from a public key. When serializing a public_data object, the
    input_hash is multplied into A_sum. This is so the object can be stored
    as public key for wallet rescanning later, or to vend to light clients.
    For the light client, a `_parse` function is added which parses the
    compressed public key serialization into a `public_data` object.
    
    Finally, add test coverage for the recieiving API.
    4e0e58fe32
  6. silentpayments: add examples/silentpayments.c
    Demonstrate sending, scanning, and light client scanning.
    dfeba02d8f
  7. silentpayments: add benchmarks for scanning
    Add a benchmark for a full transaction scan and for scanning a single
    output. Only benchmarks for scanning are added as this is the most
    performance critical portion of the protocol.
    55f6bdfa74
  8. tests: add BIP-352 test vectors
    Add the BIP-352 test vectors. 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
    a794d23e9a
  9. ci: enable silentpayments module 746abfb79d
  10. docs: update README 86d85076e0
  11. add dleq implementation
    - modify secp256k1-zkp's dleq implementation to be consistent with
      BIP 374.
    - use BIP374 notations.
    - add DLEQ tests
    cec4d3553a
  12. add BIP374 test vectors
    - test vectors 0..5 are from test_vectors_generate_proof.csv
      (only those test vectors with secp generator point here)
        - test vectors 0, 1, 2 are valid test cases
        - test vectors 3, 4, 5 are invalid test cases
    - test vectors 6..12 are from test_vectors_verify_proof.csv
        - test vectors 0, 1, 2 are present in this file too
    9948bf1bee
  13. add secp256k1_silentpayments_create_shared_secret_with_proof
    - add new internal function which returns both DLEQ proof and
      shared secret.
    - the existing secp256k1_silentpayments_create_shared_secret API
    is refactored to use
    secp256k1_silentpayments_create_shared_secret_with_proof.
    b5ef01f1fb
  14. introduce struct to hold DLEQ proof related data for silent payments
    - structure contains 33-byte shared secret point + 64-byte DLEQ proof
      + index of recipient in original unsorted array of silent payment
        recipients
    - add functions to serialise and parse the structure to/from bytes
    fae6014f34
  15. add secp256k1_silentpayments_sender_create_outputs_with_proof
    - add new API which returns DLEQ proofs along with outputs for recipients
    - the existing API secp256k1_silentpayments_sender_create_outputs simply
      calls secp256k1_silentpayments_sender_create_outputs_with_proof
      internally.
    22e4b40697
  16. add secp256k1_silentpayments_verify_proof 34b1649689
  17. add tests for creating and verifying proofs
    - in examples/silentpayments.c
        - sender now generates outputs with proof and verifies the proof
        - proof can be serialised to bytes and sent to recipient
        - bytes can be parsed back to proof by recipient as well
        - recipient can verify proof
    - in tests_recipients_helper, run_silentpayments_test_vector_send
        - along with output checks, generate DLEQ proofs and verify them
    
    add detailed examples showing parsing/serialisation
    ea9236a6b7


stratospher


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin-core/secp256k1. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2025-02-07 17:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me