-
Notifications
You must be signed in to change notification settings - Fork 19
Add Silent Payments for the Liquid Network #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
42Pupusas
wants to merge
10
commits into
ElementsProject:main
Choose a base branch
from
42Pupusas:elip-silent-payments-liquid
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+152
−0
Open
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
d092ef7
Add Silent Payments for the Liquid Network draft
42Pupusas ab997b4
Condense Silent Payments for Liquid ELIP per reviewer feedback
42Pupusas ab0c3d6
Condense light-client receive section to a single paragraph
42Pupusas 5f2a62c
Make Taproot the output representation, matching BIP-352 exactly
42Pupusas 0124bbb
Fix SP address HRP collision with native Liquid; drop standalone Labe…
42Pupusas 8d634b1
Scope down Reference Implementation section
42Pupusas c40601e
Silent Payments for Liquid: pin hash tags, fix Privacy rationale
42Pupusas 520320e
Condense spec to BIP-352 style; fix Privacy, refs, and prose
42Pupusas 237599c
Link both reference implementations (Rust and Python)
42Pupusas 28d6c18
Tighten Differences-from-BIP-352 section and surrounding prose
42Pupusas File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| <pre> | ||
| ELIP: ? | ||
| Layer: Applications | ||
| Title: Silent Payments for the Liquid Network | ||
| Author: 42pupusas <technology@illuminodes.com> | ||
| Comments-Summary: No comments yet. | ||
| Comments-URI: https://github.com/ElementsProject/elips/wiki/Comments:ELIP-???? | ||
| Status: Draft | ||
| Type: Standards Track | ||
| Created: 2026-06-01 | ||
| License: BSD-3-Clause | ||
| </pre> | ||
|
|
||
| ==Abstract== | ||
|
|
||
| This document specifies Silent Payments for the Liquid Network. The key derivation, | ||
| address format, scanning, and spending follow BIP-352<ref name="bip352">BIP-352: Silent Payments. https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki</ref> | ||
| exactly. This specification only adds Liquid-specific differences. | ||
|
|
||
| ==Motivation== | ||
|
|
||
| Confidential Transactions (CT)<ref name="ct">Confidential Transactions. https://elementsproject.org/features/confidential-transactions</ref> | ||
| hide a Liquid output's asset and amount but not its | ||
| script. A receiver with one published address has to either reuse it, (linking | ||
| all their payments) or run an interactive protocol to hand out fresh ones. Silent | ||
| Payments remove that trade-off: one static address, a distinct unlinkable output per payment. | ||
|
|
||
| ==Specification== | ||
|
|
||
| We reuse the notation, functions, and conventions of BIP-352. In particular, | ||
| <code>serP(P)</code> is the SEC1 compressed encoding of a point, <code>ser32(i)</code> | ||
| serializes a 32-bit unsigned integer most-significant-byte first, <code>n</code> is the | ||
| secp256k1 curve order, and <code>hash<sub>tag</sub>(x)</code> denotes | ||
| <code>SHA256(SHA256(tag) || SHA256(tag) || x)</code> as defined in | ||
| BIP-340<ref name="bip340">BIP-340: Schnorr Signatures for secp256k1. https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki</ref>. | ||
|
|
||
| We additionally define: | ||
|
|
||
| * Let <code>blind_tag</code> be the exact 26-byte ASCII string <code>LiquidSilentPayments/Blind</code>. | ||
| A mismatch in these bytes breaks unblinding across implementations. The tag is disjoint | ||
| from BIP-352's <code>BIP0352/SharedSecret</code>, so the blinding key and the BIP-352 | ||
| output tweak, though both derived from <code>S</code>, do not reveal each other. | ||
|
|
||
| A silent payment on Liquid is a BIP-352 output that is additionally made a confidential | ||
| Liquid output, blinded to a per-output blinding key derived from the same shared secret. | ||
| The sender, for each output index <code>k</code>: | ||
|
|
||
| * Let <code>S</code> be the shared secret and <code>P_k</code> the output public key, derived as in BIP-352 | ||
| * Let <code>scriptPubKey = OP_1 <x_only(P_k)></code>, a BIP-341<ref name="bip341">BIP-341: Taproot: SegWit version 1 spending rules. https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki</ref> Taproot output | ||
| * Let <code>bk_k = int(hash<sub>blind_tag</sub>(serP(S) || ser32(k))) mod n</code> | ||
| ** If <code>bk_k = 0</code>, increment <code>k</code> and continue | ||
| * Let <code>BK_k = bk_k·G</code> | ||
| * Blind the output's asset and amount to <code>BK_k</code>, as for any confidential Liquid output | ||
| The receiver, having recomputed <code>S</code> as in BIP-352, recomputes | ||
| <code>bk_k</code> and unblinds the output with no out-of-band exchange. Deriving the | ||
| blinding key from <code>S</code> avoids both a fixed address-level blinding key (which | ||
| would link a receiver's outputs) and an interactive per-output exchange. | ||
|
|
||
| ===Differences from BIP-352=== | ||
|
|
||
| * '''Output format.''' The output is a ''confidential'' Liquid Taproot<ref name="bip341" /> output, with its asset and amount blinded to <code>BK_k</code>, rather than a bare Taproot output. | ||
| * '''<code>outpoint_L</code> encoding.''' Outpoints use the Elements consensus encoding (32-byte txid in internal byte order followed by 4-byte little-endian <code>vout</code>) in place of BIP-352's Bitcoin encoding. | ||
| * '''Address HRP.''' The human-readable part is <code>lqsp</code> (mainnet) or <code>tlqsp</code> (testnet and regtest) — distinct from <code>ex</code>/<code>tex</code>, <code>lq</code>/<code>tlq</code>, and Bitcoin's <code>sp</code>/<code>tsp</code>. The address payload, version symbol (<code>q</code>), and relaxed Bech32 length limit are unchanged from BIP-352. | ||
| * '''Light-client scanning.''' The BIP-158<ref name="bip158">BIP-158: Compact Block Filters for Light Clients. https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki</ref> compact-filter step is unnecessary: CT does not blind the <code>scriptPubKey</code>, so a client matches its derived candidate scripts directly against the public output scripts. The BIP-352 tweak server<ref name="indexserver">BIP-352 Silent Payments index server. https://github.com/bitcoin/bips/blob/master/bip-0352/index-server.mediawiki</ref> (publishing <code>T = input_hash·A</code> per transaction) is used unchanged. | ||
| Everything else follows BIP-352 exactly: input eligibility, the even-Y rule, | ||
| <code>input_hash</code>, <code>S = input_hash·a·B_scan</code>, the output tweak | ||
| <code>t_k</code>, labels, gap-limit scanning, and the Taproot key-path spend with | ||
| <code>d = b_spend + t_k</code>. | ||
|
|
||
| ===Privacy=== | ||
|
|
||
| Detecting or unblinding a silent payment requires the Diffie-Hellman shared secret | ||
| <code>S = input_hash·a·B_scan = b_scan·(input_hash·A)</code>. Computing it needs either the | ||
| sender's input secret <code>a</code> or the receiver's secret scan key <code>b_scan</code>, | ||
| so this inherits the BIP-352 privacy model. CT adds one thing on top: even someone who | ||
| holds <code>b_scan</code> learns only that an output is a silent payment, not its amount or asset. | ||
|
|
||
| ==Test Vectors== | ||
|
|
||
| All byte strings are hex. Receiver keys: | ||
|
|
||
| <pre> | ||
| b_scan = 1111111111111111111111111111111111111111111111111111111111111111 | ||
| b_spend = 2222222222222222222222222222222222222222222222222222222222222222 | ||
| </pre> | ||
|
|
||
| Two eligible inputs: | ||
|
|
||
| <pre> | ||
| input 0: priv = 3131...31 (0x31 x32), outpoint txid = 1010...10 (0x10 x32), vout = 0 | ||
| input 1: priv = 3232...32 (0x32 x32), outpoint txid = 2020...20 (0x20 x32), vout = 1 | ||
| </pre> | ||
|
|
||
| Aggregated values (<code>outpoint_L</code> = input 0, the lexicographically smaller): | ||
|
|
||
| <pre> | ||
| A = 031195a8046dcbb8e17034bca630065e7a0982e4e36f6f7e5a8d4554e4846fcd99 | ||
| input_hash = d392922c00280a7e8d282182f5026f2fddbc74c1e1de18b4822128b2b77ec641 | ||
| </pre> | ||
|
|
||
| Per-output values: | ||
|
|
||
| <pre> | ||
| k = 0: | ||
| P_k = 02a29d9716417c964ca9e477343e71ffe730a4991a3eaad668eabec84e9feb7931 | ||
| BK_k = 0344e1289497e6da66fde710d2f38de053fc07355e405524401d7d609df5a1a8cc | ||
| bk_k = 70ab8897b64bd21b427339ff4d014b883191ef6425862246c53bfc27a59aa3f0 | ||
| spend priv = f03c436d2cd67ae1fecf7d88a38aa3a03c0abea43feaf6da8eb71e2e3a866bda | ||
| scriptPubKey = 5120a29d9716417c964ca9e477343e71ffe730a4991a3eaad668eabec84e9feb7931 | ||
|
|
||
| k = 1: | ||
| P_k = 0229d77654023af267dbe9cb7ff1956f947c816f203494381308387168fb010c92 | ||
| BK_k = 03efdeda770ccdbe8bf466fba48bfd2b2c436ab0c04658fc6d6c277de5078129fa | ||
| bk_k = 945ba73a9804f62089c7d2ffdc079031031f0aebab372cec17ef9c110ebceb10 | ||
| spend priv = 9eff3472230fc83ef5ea8f8c80401c4eecd595a048bd2482a107d3a49baa5a58 | ||
| scriptPubKey = 512029d77654023af267dbe9cb7ff1956f947c816f203494381308387168fb010c92 | ||
| </pre> | ||
|
|
||
| Mainnet address (HRP <code>lqsp</code>): | ||
|
|
||
| <pre> | ||
| lqsp1qqd8n2k7uklxq4aegau7vawtptkgxsja4kt99lpv6krctwpq8tpc65qjxd4lu4etruh9sngx3su9mtqp5fqzxz7re59y5nnez9p03ht3lyudcfhfe | ||
| </pre> | ||
|
|
||
| Because blinding factors are randomized per output, the blinded output is not | ||
| byte-reproducible. What matters is that an output blinded to <code>BK_k</code> | ||
| unblinds under <code>bk_k</code> and under no other key. | ||
|
|
||
| ==Backwards Compatibility== | ||
|
|
||
| No consensus change. A silent-payment output is an ordinary confidential Taproot output, | ||
| spent by an ordinary key-path signature, so existing relay and validation rules apply. | ||
| Wallets that don't implement this are unaffected. | ||
|
|
||
| ==Reference Implementations== | ||
|
|
||
| * Rust: https://github.com/42Pupusas/elip-sp-reference/blob/main/src/lib.rs | ||
| * Python: https://github.com/42Pupusas/elip-sp-reference/blob/main/python/elip_sp_reference/core.py | ||
| ==Acknowledgements== | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JAN3 should be in the acknowledgements if this BIP is awarded the bounty |
||
|
|
||
| This specification builds on BIP-352, the BIP-352 index server specification<ref name="indexserver" />, | ||
| and the Confidential Transactions work of the Elements Project<ref name="ct" />. | ||
|
|
||
| The authors thank JAN3 for sponsoring and supporting this work. | ||
|
|
||
| ==References== | ||
|
|
||
| <references /> | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be moved to this repo. Follow the convention in https://github.com/bitcoin/bips/blob/master/bip-0352/reference.py and use MIT license
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay ignore my comment about MIT license as other ELIPS are BSD license as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean the reference implementations? I noticed all the other ELIPs had external reference implementations so did it that way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think they are almost always in https://github.com/ElementsProject/elements and thats why. Having them in a personal repo seems wrong or atleast different from the conventions in the bips repo