Skip to content

silentpayments: add light client API - #1912

Open
theStack wants to merge 8 commits into
bitcoin-core:masterfrom
theStack:silentpayments_module_lightclient_api
Open

silentpayments: add light client API#1912
theStack wants to merge 8 commits into
bitcoin-core:masterfrom
theStack:silentpayments_module_lightclient_api

Conversation

@theStack

Copy link
Copy Markdown
Contributor

This PR extends the silentpayments module with API functions for prevouts_summary (de)serialization and output public key (k=0) creation, intended to be used by tweak indexers and light clients. Note that this functionality was originally introduced in the take 3 PR (#1698), but was then later intentionally removed again in take 4 (#1765, recently merged and released), in order to reduce the scope and lower the review burden.

The following 3 API functions are added:

  • secp256k1_silentpayments_recipient_prevouts_summary_serialize: given a prevouts_summary object, create the corresponding 33-bytes or 65-bytes serialization
  • secp256k1_silentpayments_recipient_prevouts_summary_parse: given a 33-byte or 65-byte prevouts_summary representation, create the corresponding prevouts_summary object
  • secp256k1_silentpayments_recipient_create_output_pubkeys: given a prevouts_summary object, a recipients scan secret key and a list of spend public keys, create a list of corresponding x-only output public keys (one for each spend public key, each derived with k=0).

Tests, benchmarks and the example are extended accordingly.

theStack and others added 8 commits August 19, 2026 20:09
…zation

Co-authored-by: josibake <josibake@protonmail.com>
Best reviewed with `--ignore-all-space` (or `-w` for short).
This is preparatory for introducing the light client API function in the
next commit. To keep the current call-site which only creates a single
output pubkey (in `_sender_create_outputs`) as-is, a corresponding wrapper
function calls the new function with one spend pubkey.
No behaviour or API change in this commit yet.

Best reviewed with `--ignore-all-space` (or `-w` for short).
Add function for creating k=0 outputs for multiple spend public keys.
These keys can then be checked for existance against the UTXO set/blockchain.

If a match is found, the client needs to download the full transaction and
rescan with `_scan_outputs`.

Co-authored-by: josibake <josibake@protonmail.com>
Co-authored-by: josibake <josibake@protonmail.com>
TODO: also test with 65-byte sized prevout_summary serializations
@theStack
theStack force-pushed the silentpayments_module_lightclient_api branch from c337dd6 to 0b1cde3 Compare August 19, 2026 18:11
@theStack

Copy link
Copy Markdown
Contributor Author

Rebased on master (adapting to the _eckey_pubkey_... -> _ge_... serialize/parse renames #1915) and fixed the unintentional accepting of prevouts_summary deserialization if they are in hybrid pubkey format (i.e. 65 bytes with prefix bytes 0x06 or 0x07). This will be a bit simpler and more explicit if #1918 gets in and secp256k1_ge_parse{33,65} can be used, added a TODO comment accordingly.

@bitsagarob

Copy link
Copy Markdown

Tested ACK 0b1cde3

Exercised the new light client API against real chain data rather than constructed inputs: the 33-byte tweak a BlindBit Oracle v2 serves for a real 50,000 sat silent payment in mainnet block 965085, paid to a throwaway wallet whose scan key is published.

1. parse the 33-byte tweak the oracle serves
   ok
2. scan that transaction's one output
   found f420241ebdee9a956f88f6ea704b1e02871a64082f61489150222c3a33ee6038
   MATCHES the real 50,000 sat payment
3. round-trip: serialize the parsed summary back to 33 bytes
   in  023497fcdef5a9254be2e60e02a53bcede1e3d4ab67ed1928140a1d69438bb5678
   out 023497fcdef5a9254be2e60e02a53bcede1e3d4ab67ed1928140a1d69438bb5678
   identical
4. the 65-byte form should scan identically
   same payment found via 65-byte form
5. create_output_pubkeys, the filter-matching path, from the same tweak
   k=0 candidate f420241ebdee9a956f88f6ea704b1e02871a64082f61489150222c3a33ee6038
   equals the real output, so a filter would hit

Step 3: the 33-byte serialization is byte-identical to the deployed BlindBit wire format, so an index server can hand its bytes straight to _prevouts_summary_parse.

Tested with:
cmake -B build -DSECP256K1_ENABLE_MODULE_SILENTPAYMENTS=ON -DSECP256K1_BUILD_BENCHMARK=ON
cmake --build build -j8 && ctest --test-dir build — 223/223 passed
x86-64 Linux, gcc 13.3.0. ctime_tests needs valgrind headers I don't have here, unrelated to this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants