Privacy is coming to BTC in the form of Silent Payments
Exploring the Development of a libsecp256k1 Silent Payments Module
In our recent CoreDev meeting, an exciting idea emerged: creating a libsecp256k1 Silent Payments (BIP352) module to handle the low-level components of the protocol. As someone who’s dived deep into BIP352 and its current implementation (see bitcoin/bips#1458 and tracking issue bitcoin/bitcoin#28536), I’d like to share some insights and open up a discussion on the potential scope and design of this module.
Understanding Silent Payments (BIP352)
Silent Payments is an innovative protocol designed to enhance privacy in Bitcoin transactions. Instead of requiring the sender to interact directly with the recipient’s address, Silent Payments allow the recipient to scan the blockchain for payments intended for them without revealing their address publicly. This is achieved through a series of cryptographic computations, which are perfect candidates for a dedicated libsecp256k1 module.
Defining the Scope: What Should the Module Include?
The primary goal of the proposed libsecp256k1 Silent Payments module is to manage the complex mathematical operations required by the protocol. This would not only benefit Bitcoin Core but also other projects needing these computations. Here are the key components:
1. Calculating the Outpoints Hash
One of the first steps in the Silent Payments protocol involves calculating a hash of outpoints. This process requires sorting a list of 36-byte serialized outpoints and then applying a SHA256 hash.
Possible Approaches:
- Have the module handle both sorting and hashing.
- Let the caller handle sorting, while the module handles hashing.
- Require the caller to manage both sorting and hashing.
My Take: For simplicity, I lean towards the third option. This approach keeps libsecp256k1 focused on elliptic curve cryptography (ECC) tasks and avoids introducing transaction-specific logic into the library. Moreover, Bitcoin Core’s SHA256 implementation is more optimized than libsecp256k1’s, making it sensible to leave hashing outside the module.
2. Calculating the Sum Tweak of Input Private Keys
On the sender side, we need to sum private keys, with special handling for those used in taproot outputs to enforce even y parity.
Interface Options:
- Pass two separate lists for pre-taproot and taproot private keys.
- Use a structure that includes a flag for enforcing even y parity.
My Take: While neither option is perfect, passing two lists seems less confusing. This way, users explicitly handle different types of private keys, ensuring clarity.
3. Calculating the Sum Tweak of Input Public Keys
For the receiver, public keys need to be summed. Public keys come in various formats and sizes, complicating the interface design.
Interface Options:
- Pass two lists: one for
secp256k1_pubkey
and one forsecp256k1_xonly_pubkey
. - Provide a conversion function to standardize the public key format.
My Take: Passing two lists is straightforward and avoids ambiguity. Additionally, a conversion function could be a useful utility for users who need it.
4. Calculating the Shared Secret Using Unhashed ECDH
Both sides of the transaction need to calculate a shared secret using an unhashed Elliptic Curve Diffie-Hellman (ECDH) function.
My Take: This function is a natural fit for the library. Users should not need to define custom “not-a-hash” functions, so including this operation in the module makes sense.
Conclusion
Developing a libsecp256k1 Silent Payments module is a significant step towards enhancing privacy in Bitcoin transactions. By carefully defining the scope and designing a user-friendly interface, we can create a powerful tool that supports not just Bitcoin Core but other projects as well. This new paradigm will be essential in helping BTC become a more robust and versatile asset type and thus a positive sign of future price performance.