Silent Payments: Sending (take 2) #35302

pull Eunovo wants to merge 16 commits into bitcoin:master from Eunovo:implement-bip352-sending changing 54 files +17558 −59
  1. Eunovo commented at 4:16 AM on May 16, 2026: contributor

    This PR is part of integrating silent payments into Bitcoin Core. It is the second iteration of #28201. Status and tracking for the project is managed in #28536

    Prerequisite PRs:

    Sending

    Silent Payments logic The main focus of this PR is:

    • Applying the Taptweak to a taproot internal private key (this is a copy-paste of the code for applying the taptweak in the signing process)
    • Getting a private key from a given scriptPubKey
    • Creating silent payment outputs
    • Applying the created scriptPubKeys back to the vector of CRecipients
    • The functions are then used together to create silent payment outputs during CreateTransactionInternal.

    Final steps The last commits ensure that:

    • Coin selection is silent payments aware and knows to exclude taproot script path spends and inputs with unknown witness when funding a transaction which pays to a silent payment address
    • The change output type is correctly chosen when paying to a silent payment address
    • Functional tests
  2. Squashed 'src/secp256k1/' changes from 7262adb4b4..14be7f2abe
    14be7f2abe silentpayments: skip slow benchmarks for low iters count (<= 2)
    ea46d6502e docs: update README
    8587aeb029 ci: enable silentpayments module
    1375d38a32 tests: add sha256 tag test
    eb3748dab1 tests: add constant time tests
    e1674f389a tests: add BIP-352 test vectors
    9163035ab7 silentpayments: optimize scanning by using batch inversion
    dc36ff6ec3 silentpayments: add benchmarks for scanning
    b7f09f3eb5 silentpayments: add examples/silentpayments.c
    460565c662 silentpayments: respect per-group recipients protocol limit (K_max=2323)
    72658fc85e silentpayments: receiving
    c7a64d0cd8 silentpayments: recipient label support
    be56a66992 silentpayments: sending
    7bfae739e3 build: add skeleton for new silentpayments (BIP352) module
    b11340b3ce Merge bitcoin-core/secp256k1#1849: musig: always clear out secret key in `secp256k1_musig_nonce_gen_counter`
    8479eafa57 musig: always clear out secret key in `secp256k1_musig_nonce_gen_counter`
    c1a9e4fe64 Merge bitcoin-core/secp256k1#1848: ci: Bump GCC snapshot major version to 17
    3cca6451a2 ci: Bump GCC snapshot major version to 17
    ea174fe045 Merge bitcoin-core/secp256k1#1846: ci: Replace `ilammy/msvc-dev-cmd` with manual MSVC setup
    285cb788e9 ci: Replace `ilammy/msvc-dev-cmd` with manual MSVC setup
    
    git-subtree-dir: src/secp256k1
    git-subtree-split: 14be7f2abe4797c1a58249cb901cc6f02972cb4d
    bb1bce36cf
  3. Merge commit 'bb1bce36cf8b9292a65f0f03ab855e7133357b9f' into new-sp-base ece2374760
  4. crypto: add read-only method to KeyPair
    Add a method for passing a KeyPair object to secp256k1 functions expecting a secp256k1_keypair.
    This allows for passing a KeyPair directly to a secp256k1 function without needing to create a
    temporary secp256k1_keypair object.
    bccfd81105
  5. Add "sp" HRP 602835e080
  6. Add V0SilentPaymentDestination address type ba4b734ec8
  7. common: add bip352.{h,cpp} secp256k1 module
    Wrap the silentpayments module from libsecp256k1. This is placed in
    common as it is intended to be used by:
    
      * RPCs: for parsing addresses
      * Wallet: for sending, receiving, spending silent payment outputs
      * Node: for creating silent payment indexes for light clients
    6355a90494
  8. wallet: disable sending to silent payment address
    Have `IsValidDestination` return false for silent payment destinations
    and set an error string when decoding a silent payment address.
    
    This prevents anyone from sending to a silent payment address before
    sending is implemented in the wallet, but also allows the functions to
    be used in the unit testing famework.
    e12280b9d6
  9. tests: add BIP352 test vectors as unit tests
    Use the test vectors to test sending and receiving. A few cases are not
    covered here, namely anything that requires testing specific to the
    wallet. For example:
    
    * Taproot script path spending is not tested, as that is better tested in
      a wallets coin selection / signing logic
    * Re-computing outputs during RBF is not tested, as that is better
      tested in a wallets RBF logic
    
    The unit tests are written in such a way that adding new test cases is
    as easy as updating the JSON file
    0520567fb5
  10. wallet: get serialized size for `V0SilentPayments`
    BIP352 v0 specifies that a silent payment output is a taproot output.
    Taproot scriptPubKeys are a fixed size, so when calculating the
    serialized size for a CRecipient with a V0SilentPayments destination,
    use WitnessV1Taproot for the serialized txout size.
    209b40626a
  11. wallet: add method for retreiving a private key
    Add a method for retreiving a private key for a given scriptPubKey.
    If the scriptPubKey is a taproot output, tweak the private key with the
    merkle root or hash of the public key, if applicable.
    f9a10e9ea9
  12. wallet: make coin selection silent payment aware
    Add a flag to the `CoinControl` object if silent payment destinations
    are provided. Before adding the flag, call a function which checks if:
    
    * The wallet has private keys
    * The wallet is unlocked
    
    Without both of the above being true, we cannot send to a silent payment
    address.
    
    During coin selection, if this flag is set, skip taproot inputs when
    script spend data is available. This is based on the assumption that if
    a user provides script spend data, they don't have access to the key
    path spend. As future improvement, we could instead check to see if we
    have access to the key path spend, and only exclude the output when we
    don't regardless of whether or not the user provides script spend data.
    
    Also skip UTXOs of type `WITNESS_UNKNOWN`, although it is very unlikely
    our wallet would ever try to spend a witness unknown output.
    e3ef349ad5
  13. wallet: add `IsInputForSharedSecretDerivation` function 9898826eef
  14. wallet: add `CreateSilentPaymentOutputs` function
    `CreateSilentPaymentsOutputs` gets the correct private keys, adds them
    together, groups the silent payment destinations and then generates the
    taproot script pubkeys. These are then passed back to
    CreateTransactionInternal, which uses these scriptPubKeys to update
    vecSend before adding them to the transaction outputs.
    efbdd793f5
  15. wallet: update TransactionChangeType
    If sending to a silent payment destination, the change type should be taproot
    334c36a2e5
  16. wallet: enable sending to silent payment address
    Treat silent payment addresses as valid destination. Also disable using
    silent payment addresses with the `addr()` descriptor, as this
    descriptor expects an encoding of a scriptPubKey, whereas a silent
    payment address consists of instructions on how to generate a
    scriptPubKey for the recipient.
    
    Co-authored-by: Oghenovo Usiwoma <37949128+eunovo@users.noreply.github.com>
    71bfa7d3ef
  17. tests: add sending functional tests 03c835dbd6
  18. DrahtBot commented at 4:16 AM on May 16, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/35302.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process. A summary of reviews will appear here.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #34697 (descriptor: fix musig duplicate checks and origin handling by shuv-amp)
    • #34405 (wallet: skip APS when no partial spend exists by 8144225309)
    • #32763 (wallet: Replace CWalletTx::mapValue and vOrderForm with explicit class members by achow101)
    • #31974 (Drop testnet3 by Sjors)
    • #28333 (wallet: Construct ScriptPubKeyMans with all data rather than loaded progressively by achow101)
    • #27260 (Enhanced error messages for invalid network prefix during address parsing. by portlandhodl)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-05-19 06:51 UTC