From ae247aa6cfe512d647fa1178b161213b7187d225 Mon Sep 17 00:00:00 2001 From: Alfred Hodler <100861939+alfred-hodler@users.noreply.github.com> Date: Fri, 22 Jul 2022 08:51:32 +0000 Subject: Private payments BIP --- bip-alfredhodler-privatepayments.mediawiki | 238 +++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 bip-alfredhodler-privatepayments.mediawiki diff --git a/bip-alfredhodler-privatepayments.mediawiki b/bip-alfredhodler-privatepayments.mediawiki new file mode 100644 index 0000000..2abfafb --- /dev/null +++ b/bip-alfredhodler-privatepayments.mediawiki @@ -0,0 +1,238 @@ +
+ BIP: ? + Layer: Applications + Title: Private Payments + Author: Alfred Hodler+ +In the following text the BIP number is provisionally set to 999 for technical purposes until a BIP number is assigned. + +==Abstract== + +This BIP makes it possible for two parties to transact using addresses that only they can calculate. This is done using exclusively on-chain methods and in a manner that minimizes blockchain footprint. Receiving parties can share their payment codes publicly without a loss of privacy, as every sender will calculate a unique set of addresses for each payment code. + +==Motivation== + +A recipient that wishes to receive funds normally has several options: + +# Sharing a static address. +# Sharing a BIP32 extended public key. +# Using a payment server. +# Sharing a BIP47 payment code. + +The first method works well enough for one-time payments between two parties as long as the address is shared through a private channel. It does not work well for recurring payments because address reuse leads to a loss of privacy. Using this method for donations exacerbates the problem since the address will serve as a focal point for data collection and analysis. + +The second method works only for recurring payments between two parties. Furthermore, it does not say anything about address types and makes it possible for a sender to send to a script that a recipient cannot spend from. + +The third method works in the case of recipients that have the resources to set up and maintain a payment server that will generate a fresh address for each payment. These are usually businesses and the method is usually out of reach for the average user. + +The fourth method addresses most of the above shortcomings. However, it introduces the following problems: + +* The BIP does not say anything about address types. Receiving wallets therefore have to watch all address types that can be created from a single public key. Even then, a sender could send to a script that a receipient cannot spend from. + +* The BIP uses a notification mechanism that relies on publicly known per-recipient notification addresses. If Alice wants to send funds to Bob, she has to use the same notification address that everyone else uses to notify Bob. If Alice is not careful with coin selection, i.e. ensuring that her notification UTXO is not linked to her, she will publicly expose herself as someone who is trying to send funds to Bob and their relationship becomes permanently visible on the blockchain. + +==Method== + +When Alice wants to start paying Bob in private, she imports his payment code into a compatible wallet. Her wallet extracts Bob's public key from the payment code, constructs a notification transaction and sends it to a static address that all users of this BIP watch. If Bob finds a notification transaction addressed to himself, he imports Alice's public key contained therein and stores it. Bob then performs ECDH using Alice's public key and his own private key in order to calculate a common set of addresses to watch. Alice calculates the same set of addresses on her end and uses them to send coins to Bob. If Alice engages in coin control, both the initial notification transaction and subsequent payment transactions cannot be attributed to either party. Even if Alice uses coins that are already associated with her, chain analysis will identify her as a sender but Bob's privacy will remain entirely preserved. + +==Specification== + +===Definitions=== + +* Alice: sender +* Bob: recipient +* Payment code: static string that Bob generates and shares with others so that he can receive payments +* P: public key contained in Bob's payment code +* p: private key associated with Bob's public key P +* N: extended public key used by Alice to derive child keys for each Bob she wants to transact with +* n: private key associated with Alice's public key N +* x: Alice's secret recipient index, unique for each Bob +* N_x: child public key derived from N at index x (non-hardened) +* n_x: private key associated with N_x +* Q: static notification address associated with this BIP +* q: private key that can spend from Q +* c: Alice's transaction count toward Bob +* p_c: Bob's private key at index c +* P_c: Bob's public key at index c +* A_c: Bob's receive address at index c +* *: EC multiplication +* +: EC addition +* |: string concatenation + +The values of q and Q are: + +* q:+ Status: Draft + Type: Informational + Created: 2022-07-10 + License: MIT +
0x6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d
+* Q (mainnet): bc1qz9380vammj5zcz5sjs65yxp6q7qq74klxjycw8
+* Q (testnet): tb1qz9380vammj5zcz5sjs65yxp6q7qq74klv5lt45
+
+===Public Key Derivation Path===
+
+The derivation path for this BIP follows BIP44. The following BIP32 path levels are defined:
+
+
+m / purpose' / coin_type' / account'
+
+
+purpose
is set to 999.
+
+(p, P)
and (n, N)
are keys associated with the above path, depending on which side is performing the calculation.
+
+N_x keys are the direct non-hardened children of N. For instance, the path of N_0
from N
is m / 0
.
+
+===Payment Code Structure and Encoding===
+
+* bytes [0..1]
: address type flags (2 bytes, inclusive)
+* bytes [2..35]
: compressed public key P (33 bytes, inclusive)
+
+Payment codes are encoded in bech32m and the human readable part is "pay" for mainnet and "payt" for testnet (all types), resulting in payment codes that look like "pay1cqqq8d29g0a7m8ghmycqk5yv24mfh3xg8ptzqcn8xz6d2tjl8ccdnfkpjl7p84".
+
+===Address Types===
+
+Address type flags determine which address types a payment code accepts. This is represented by big-endian ordered 16 bits. For instance, a hypothetical payment code that handles all address types will have all defined bits set to 1.
+
+Currently defined flags:
+
+* 0x0001 - P2PKH
+* 0x0002 - P2WPKH
+* 0x0004 - P2TR
+
+The remaining flags are reserved for future address types.
+
+===Notifications===
+
+Notifications are performed by publishing transactions that contain two outputs:
+
+# minimal P2WPKH output to Q (minimal with respect to some dust threshold).
+# OP_RETURN containing a 67-byte notification payload.
+
+The purpose of the output sending to Q is so that BIP157/158 compatible clients can use compact block filters to detect notifications without having to download every block. This enables the usage of the standard in resource constrained environments. The reason the address is static is so that privacy loss cannot occur through graph building. The private key that can spend from Q is publicly known in order to incentivize UTXO consolidation by random parties.
+
+The value of the OP_RETURN output is constructed using the following formula:
+
+notification_code | N_x | address_types
+
+* notification_code
is SHA256(n_x * P)
(32 bytes)
+* N_x
is the unique public key a sender is using for a particular recipient (33 bytes)
+* address_types
is a two-byte bitarray whose bits are set to a subset of the ones representing recepients's accepted address types
+
+When Alice wants to notify Bob that he will receive future payments from her, she performs the following procedure:
+
+# Assigns an unused, unique index x
to Bob (0 if Bob is the first party she is notifying).
+# Calculates a notification code: notification_code = SHA256(n_x * P)
+# Commits to a subset of Bob's accepted address types by constructing address_types
. Going forward Alice must not send to address types she did not commit to in the notification.
+# Constructs a notification payload by concatenating the above values according to the formula.
+# Selects any UTXO in her wallet, preferably not associated with her.
+# Sends a transaction with one output to Q and one OP_RETURN output whose value is set to the 67 byte notification payload.
+
+When Bob notices a transaction to Q, he extracts the 67 byte payload from the second output and performs the following procedure:
+
+# Breaks down the payload into its three constituent parts.
+# Selects N_x
(item #1) and performs SHA256(N_x * p)
(Bob does not know the value of x
).
+# If the above value matches the notification value (item #0), Bob found a notification addressed to himself and stores N_x
.
+# If this process fails for any reason, Bob assumes a spurious notification or one not addressed to himself and gives up.
+
+Since changing x
yields a completely different sender identity, Alice can always re-notify Bob from a different index when she does not want to be associated with her previous identity.
+
+===Transacting===
+
+Alice initializes counter c
which is unique to Bob and increments with each transaction. c
is a 64-bit integer and must be inputted into a hasher as a big-endian encoded array of 8 bytes.
+
+1. Alice calculates a secret point (constant between Alice and Bob):
+
+
+S = n_x * P
+
+
+2. Alice calculates a shared secret:
+
+
+s = SHA256(S, c)
+
+
+3. Alice calculates Bob's ephemeral public key and its associated address where the funds will be sent:
+
+
+P_c = P + s*G
+
+
+4. Alice constructs an address using the key P_c
, using one of the address types she committed to in the notification transaction.
+
+Bob constructs his watchlist by mirroring this process on his end, except that his method of calculating S is:
+
+
+S = N_x * p
+
+
+When Bob wants to spend from such addresses, he calculates his private keys in the following manner:
+
+
+p_c = p + s
+
+
+==Test Vectors==
+
+===Alice's Wallet===
+'''BIP32 seed:''' 0xfe
+
+'''Master xprv:''' xprv9s21ZrQH143K2qVytoy3eZSSuc1gfzFrkV4bgoHzYTkgge4UoNP62eV8jkHYNqddaaefpnjwkz71P5m4EW6RuQBJeP9pdfa9WBnjP6XUivG
+
+'''n:''' xprv9xgkGJLpRhrdGVTFqS49xKyH85yUKWfkazSjWUbnaqmRf5ucc2YwruLmFwqwtZ3S3Whxgj52HoyTrtfbzDUrAseWmER9DK3TZUTorzSpkdt
+
+'''N:''' xpub6Bg6fosiG5QvUyXiwTbAKTv1g7oxiyPbxDNLJs1Q9BJQXtEm9ZsCQhfF7CEo94MBjwEz5wBmCuo5AcSeBtKDE73GfGcQ6PATzVBVfdPtY17
+
+'''x:''' 0
+
+'''n_x:''' 011447e7c6426aecd3fb3e76fba39ef3dc1e91dc578e8b535f714234c62675c5
+
+'''N_x:''' 039d138aaf5bc2e27a9740541576eceb90a5f20b4799dbfda48e5c7ca240505753
+
+===Bob's Wallet===
+'''BIP32 seed:''' 0xff
+
+'''Master xprv:''' xprv9s21ZrQH143K47bRNtc26e8Gb3wkUiJ4fH3ewYgJeiGABp7vQtTKsLBzHM2fsfiK7Er6uMrWbdDwwrdcVn5TDC1T1npTFFkdEVoMgTwfVuR
+
+'''p:''' 0x3ba93579cf5b37d18cd2e3507d51b22c3771a2dbfd1b58dd45d08a6e6ed4b965
+
+'''P:''' 0x02943ebcb1dbb1e1cb7c0350687c2c8dbdf1c4f350d849341a6ff61a595f2085e2
+
+'''Accepted scripts:''' 0x03 (legacy + segwit) (0x01 | 0x02)
+
+'''Payment code:''' pay1qqps99p7hjcahv0ped7qx5rg0skgm003cne4pkzfxsdxlas6t90jpp0zpnwgqy
+
+===Alice notifying Bob===
+'''S:''' 0x0295ac9a667d7077def44b11104811e5d91d164dd60cb08275b313a33691320cb3
+
+'''Notification code:''' 0xfbe8d683683023aaa066ba13cf79c9f8a7d3c69a4705025f3f4f4887a61eb975
+
+'''Script type commitment flags:''' 0x0002 (segwit only)
+
+'''Notification output script:''' OP_RETURN OP_PUSHBYTES_67 fbe8d683683023aaa066ba13cf79c9f8a7d3c69a4705025f3f4f4887a61eb975039d138aaf5bc2e27a9740541576eceb90a5f20b4799dbfda48e5c7ca2405057530002
+
+===Alice sending to Bob===
+'''c:''' 0
+
+'''s:''' 0xb7508ed246458221cc37d01de5d2f94be3a141180da11b78cbffdfd81a75f223
+
+'''s*G:''' 0x03e99301fb24083590fde78473d55a8435b0aed0dad65c516dfb268586fbe134be
+
+'''P_c:''' 0x03145adc275eda50ea188250f85e729b77b22f9868d024aff00ea61d552373cbba
+
+'''A_c:''' bc1q7nmrkdgg3qq3l2ggh46zwv7750q6rjux0nx27a
+
+===Bob spending===
+'''c:''' 0
+
+'''p_c:''' 0xf2f9c44c15a0b9f3590ab36e6324ab781b12e3f40abc745611d06a46894aab88
+
+==Reference==
+* [[bip-0032.mediawiki|BIP32 - Hierarchical Deterministic Wallets]]
+* [[bip-0043.mediawiki|BIP43 - Purpose Field for Deterministic Wallets]]
+* [[bip-0044.mediawiki|BIP44 - Multi-Account Hierarchy for Deterministic Wallets]]
+* [[bip-0157.mediawiki|BIP157 - Client Side Block Filtering]]
+* [[bip-0158.mediawiki|BIP158 - Compact Block Filters for Light Clients]]
+
--
cgit v1.2.3
From ab90b8e787e536ebd49583e3a9b43863a694d74e Mon Sep 17 00:00:00 2001
From: Clark Moody 0xffff
).
Currently defined flags:
-* 0x0001 - P2PKH
-* 0x0002 - P2WPKH
-* 0x0004 - P2TR
+{| class="wikitable"
+! Address Type !! Flag !! Value
+|-
+| P2PKH || 1 << 0
|| 0x0001
+|-
+| P2WPKH || 1 << 1
|| 0x0002
+|-
+| P2TR || 1 << 2
|| 0x0004
+|}
The remaining flags are reserved for future address types.
--
cgit v1.2.3
From 134120166c9535534560071738a342d854e904af Mon Sep 17 00:00:00 2001
From: Alfred Hodler <100861939+alfred-hodler@users.noreply.github.com>
Date: Sat, 23 Jul 2022 08:57:30 +0000
Subject: Improve notifications
---
bip-alfredhodler-privatepayments.mediawiki | 56 +++++++++++++-----------------
1 file changed, 25 insertions(+), 31 deletions(-)
diff --git a/bip-alfredhodler-privatepayments.mediawiki b/bip-alfredhodler-privatepayments.mediawiki
index 66487fa..0272bbe 100644
--- a/bip-alfredhodler-privatepayments.mediawiki
+++ b/bip-alfredhodler-privatepayments.mediawiki
@@ -51,8 +51,6 @@ When Alice wants to start paying Bob in private, she imports his payment code in
* x: Alice's secret recipient index, unique for each Bob
* N_x: child public key derived from N at index x (non-hardened)
* n_x: private key associated with N_x
-* Q: static notification address associated with this BIP
-* q: private key that can spend from Q
* c: Alice's transaction count toward Bob
* p_c: Bob's private key at index c
* P_c: Bob's public key at index c
@@ -61,12 +59,6 @@ When Alice wants to start paying Bob in private, she imports his payment code in
* +: EC addition
* |: string concatenation
-The values of q and Q are:
-
-* q: 0x6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d
-* Q (mainnet): bc1qz9380vammj5zcz5sjs65yxp6q7qq74klxjycw8
-* Q (testnet): tb1qz9380vammj5zcz5sjs65yxp6q7qq74klv5lt45
-
===Public Key Derivation Path===
The derivation path for this BIP follows BIP44. The following BIP32 path levels are defined:
@@ -95,51 +87,48 @@ Address type flags determine which address types a payment code accepts. This is
Currently defined flags:
{| class="wikitable"
-! Address Type !! Flag !! Value
+! Address Type !! Flag !! Flag Value !! Ordinal Value
|-
-| P2PKH || 1 << 0
|| 0x0001
+| P2PKH || 1 << 0
|| 0x0001
|| 0
|-
-| P2WPKH || 1 << 1
|| 0x0002
+| P2WPKH || 1 << 1
|| 0x0002
|| 1
|-
-| P2TR || 1 << 2
|| 0x0004
+| P2TR || 1 << 2
|| 0x0004
|| 2
|}
The remaining flags are reserved for future address types.
-===Notifications===
-
-Notifications are performed by publishing transactions that contain two outputs:
-
-# minimal P2WPKH output to Q (minimal with respect to some dust threshold).
-# OP_RETURN containing a 67-byte notification payload.
+While payment codes use 2-byte bitflag arrays, notifications use ordinal values in the form of a single byte.
-The purpose of the output sending to Q is so that BIP157/158 compatible clients can use compact block filters to detect notifications without having to download every block. This enables the usage of the standard in resource constrained environments. The reason the address is static is so that privacy loss cannot occur through graph building. The private key that can spend from Q is publicly known in order to incentivize UTXO consolidation by random parties.
+===Notifications===
-The value of the OP_RETURN output is constructed using the following formula:
+Notifications are performed by publishing transactions that contain a single 72-byte OP_RETURN output. The value of the OP_RETURN is constructed using the following formula:
-notification_code | N_x | address_types
+search_key | notification_code | N_x | address_type
+* search_key
equals BIP999
and is a static ASCII-encoded string (6 bytes)
* notification_code
is SHA256(n_x * P)
(32 bytes)
* N_x
is the unique public key a sender is using for a particular recipient (33 bytes)
-* address_types
is a two-byte bitarray whose bits are set to a subset of the ones representing recepients's accepted address types
+* address_type
is the '''ordinal''' value of a single address type that a sender wants to send to (1 byte). This must be selected from the recepient's accepted address types.
When Alice wants to notify Bob that he will receive future payments from her, she performs the following procedure:
# Assigns an unused, unique index x
to Bob (0 if Bob is the first party she is notifying).
# Calculates a notification code: notification_code = SHA256(n_x * P)
-# Commits to a subset of Bob's accepted address types by constructing address_types
. Going forward Alice must not send to address types she did not commit to in the notification.
+# Commits to one of Bob's accepted address types by choosing its ordinal value. Going forward Alice must not send to address types other than the one she committed to in the notification.
# Constructs a notification payload by concatenating the above values according to the formula.
# Selects any UTXO in her wallet, preferably not associated with her.
-# Sends a transaction with one output to Q and one OP_RETURN output whose value is set to the 67 byte notification payload.
+# Sends a transaction with a single OP_RETURN output whose value is set to the constructed payload.
-When Bob notices a transaction to Q, he extracts the 67 byte payload from the second output and performs the following procedure:
+When Bob notices an OP_RETURN starting with the search key, he performs the following procedure:
-# Breaks down the payload into its three constituent parts.
-# Selects N_x
(item #1) and performs SHA256(N_x * p)
(Bob does not know the value of x
).
-# If the above value matches the notification value (item #0), Bob found a notification addressed to himself and stores N_x
.
+# Breaks down the payload into its four constituent parts.
+# Discards the search key (item #0).
+# Selects N_x
(item #2) and performs SHA256(N_x * p)
(Bob does not know the value of x
).
+# If the above value matches the notification value (item #1), Bob found a notification addressed to himself and stores N_x
together with address_type
.
# If this process fails for any reason, Bob assumes a spurious notification or one not addressed to himself and gives up.
-Since changing x
yields a completely different sender identity, Alice can always re-notify Bob from a different index when she does not want to be associated with her previous identity.
+Since changing x
yields a completely different sender identity, Alice can always re-notify Bob from a different index when she does not want to be associated with her previous identity. Alice can also re-notify Bob when she wants to start sending to a different address type. Bob must be able to update his watchlist in that case and he can stop watching addresses associated with the old address type.
===Transacting===
@@ -180,6 +169,7 @@ p_c = p + s
==Test Vectors==
===Alice's Wallet===
+
'''BIP32 seed:''' 0xfe
'''Master xprv:''' xprv9s21ZrQH143K2qVytoy3eZSSuc1gfzFrkV4bgoHzYTkgge4UoNP62eV8jkHYNqddaaefpnjwkz71P5m4EW6RuQBJeP9pdfa9WBnjP6XUivG
@@ -194,6 +184,7 @@ p_c = p + s
'''N_x:''' 039d138aaf5bc2e27a9740541576eceb90a5f20b4799dbfda48e5c7ca240505753
+
===Bob's Wallet===
'''BIP32 seed:''' 0xff
@@ -207,14 +198,16 @@ p_c = p + s
'''Payment code:''' pay1qqps99p7hjcahv0ped7qx5rg0skgm003cne4pkzfxsdxlas6t90jpp0zpnwgqy
+
===Alice notifying Bob===
'''S:''' 0x0295ac9a667d7077def44b11104811e5d91d164dd60cb08275b313a33691320cb3
'''Notification code:''' 0xfbe8d683683023aaa066ba13cf79c9f8a7d3c69a4705025f3f4f4887a61eb975
-'''Script type commitment flags:''' 0x0002 (segwit only)
+'''Address type commitment:''' 1 (segwit)
+
+'''Notification output script:''' OP_RETURN OP_PUSHBYTES_72 424950393939fbe8d683683023aaa066ba13cf79c9f8a7d3c69a4705025f3f4f4887a61eb975039d138aaf5bc2e27a9740541576eceb90a5f20b4799dbfda48e5c7ca24050575301
-'''Notification output script:''' OP_RETURN OP_PUSHBYTES_67 fbe8d683683023aaa066ba13cf79c9f8a7d3c69a4705025f3f4f4887a61eb975039d138aaf5bc2e27a9740541576eceb90a5f20b4799dbfda48e5c7ca2405057530002
===Alice sending to Bob===
'''c:''' 0
@@ -227,6 +220,7 @@ p_c = p + s
'''A_c:''' bc1q7nmrkdgg3qq3l2ggh46zwv7750q6rjux0nx27a
+
===Bob spending===
'''c:''' 0
--
cgit v1.2.3
From fb18d17106b6115d80bf33b26ae08c74cd6ded4d Mon Sep 17 00:00:00 2001
From: Clark Moody
---
bip-alfredhodler-privatepayments.mediawiki | 97 ++++++++++++++----------------
1 file changed, 44 insertions(+), 53 deletions(-)
diff --git a/bip-alfredhodler-privatepayments.mediawiki b/bip-alfredhodler-privatepayments.mediawiki
index 0272bbe..f99ce60 100644
--- a/bip-alfredhodler-privatepayments.mediawiki
+++ b/bip-alfredhodler-privatepayments.mediawiki
@@ -44,20 +44,21 @@ When Alice wants to start paying Bob in private, she imports his payment code in
* Alice: sender
* Bob: recipient
* Payment code: static string that Bob generates and shares with others so that he can receive payments
-* P: public key contained in Bob's payment code
-* p: private key associated with Bob's public key P
-* N: extended public key used by Alice to derive child keys for each Bob she wants to transact with
-* n: private key associated with Alice's public key N
-* x: Alice's secret recipient index, unique for each Bob
-* N_x: child public key derived from N at index x (non-hardened)
-* n_x: private key associated with N_x
-* c: Alice's transaction count toward Bob
-* p_c: Bob's private key at index c
-* P_c: Bob's public key at index c
-* A_c: Bob's receive address at index c
-* *: EC multiplication
-* +: EC addition
-* |: string concatenation
+* ''P'': public key contained in Bob's payment code
+* ''p'': private key associated with Bob's public key ''P''
+* ''N'': extended public key used by Alice to derive child keys for each Bob she wants to transact with
+* ''n'': private key associated with Alice's public key ''N''
+* ''x'': Alice's secret recipient index, unique for each Bob
+* ''Nx'': child public key derived from ''N'' at index ''x'' (non-hardened)
+* ''nx'': private key associated with ''Nx''
+* ''c'': Alice's transaction count toward Bob
+* ''Pc'': Bob's public key at index ''c''
+* ''pc'': Bob's private key at index ''c''
+* ''Ac'': Bob's receive address at index ''c''
+* ''H'': SHA256 hash function
+* ''*'': EC multiplication
+* ''+'': EC addition
+* ''|'': string concatenation
===Public Key Derivation Path===
@@ -69,9 +70,9 @@ m / purpose' / coin_type' / account'
purpose
is set to 999.
-(p, P)
and (n, N)
are keys associated with the above path, depending on which side is performing the calculation.
+''(p, P)'' and ''(n, N)'' are keys associated with the above path, depending on which side is performing the calculation.
-N_x keys are the direct non-hardened children of N. For instance, the path of N_0
from N
is m / 0
.
+''Nx'' keys are the direct non-hardened children of ''N''. For instance, the path of ''N0'' from ''N'' is ''m / 0''.
===Payment Code Structure and Encoding===
@@ -102,69 +103,59 @@ While payment codes use 2-byte bitflag arrays, notifications use ordinal values
===Notifications===
-Notifications are performed by publishing transactions that contain a single 72-byte OP_RETURN output. The value of the OP_RETURN is constructed using the following formula:
+Notifications are performed by publishing transactions that contain a single 72-byte OP_RETURN
output. The value of the OP_RETURN
is constructed using the following formula:
-search_key | notification_code | N_x | address_type
+''search_key | notification_code | Nx | address_type''
-* search_key
equals BIP999
and is a static ASCII-encoded string (6 bytes)
-* notification_code
is SHA256(n_x * P)
(32 bytes)
-* N_x
is the unique public key a sender is using for a particular recipient (33 bytes)
-* address_type
is the '''ordinal''' value of a single address type that a sender wants to send to (1 byte). This must be selected from the recepient's accepted address types.
+* ''search_key'' equals "BIP999" and is a static ASCII-encoded string (6 bytes)
+* ''notification_code'' is ''H(nx * P)'' (32 bytes)
+* ''Nx'' is the unique public key a sender is using for a particular recipient (33 bytes)
+* ''address_type'' is the '''ordinal''' value of a single address type that a sender wants to send to (1 byte). This must be selected from the recepient's accepted address types.
When Alice wants to notify Bob that he will receive future payments from her, she performs the following procedure:
-# Assigns an unused, unique index x
to Bob (0 if Bob is the first party she is notifying).
-# Calculates a notification code: notification_code = SHA256(n_x * P)
+# Assigns an unused, unique index ''x'' to Bob (''0'' if Bob is the first party she is notifying).
+# Calculates a notification code: ''notification_code = H(nx * P)''
# Commits to one of Bob's accepted address types by choosing its ordinal value. Going forward Alice must not send to address types other than the one she committed to in the notification.
# Constructs a notification payload by concatenating the above values according to the formula.
# Selects any UTXO in her wallet, preferably not associated with her.
-# Sends a transaction with a single OP_RETURN output whose value is set to the constructed payload.
+# Sends a transaction with a single OP_RETURN
output whose value is set to the constructed payload.
-When Bob notices an OP_RETURN starting with the search key, he performs the following procedure:
+When Bob notices an OP_RETURN
starting with the search key, he performs the following procedure:
# Breaks down the payload into its four constituent parts.
-# Discards the search key (item #0).
-# Selects N_x
(item #2) and performs SHA256(N_x * p)
(Bob does not know the value of x
).
-# If the above value matches the notification value (item #1), Bob found a notification addressed to himself and stores N_x
together with address_type
.
+# Discards the ''search_key'' (item #0).
+# Selects ''Nx'' (item #2) and performs ''H(Nx * p)'' (Bob does not know the value of ''x'').
+# If the above value matches the notification value (item #1), Bob found a notification addressed to himself and stores ''Nx'' together with ''address_type''.
# If this process fails for any reason, Bob assumes a spurious notification or one not addressed to himself and gives up.
-Since changing x
yields a completely different sender identity, Alice can always re-notify Bob from a different index when she does not want to be associated with her previous identity. Alice can also re-notify Bob when she wants to start sending to a different address type. Bob must be able to update his watchlist in that case and he can stop watching addresses associated with the old address type.
+Since changing ''x'' yields a completely different sender identity, Alice can always re-notify Bob from a different index when she does not want to be associated with her previous identity. Alice can also re-notify Bob when she wants to start sending to a different address type. Bob must be able to update his watchlist in that case and he can stop watching addresses associated with the old address type.
===Transacting===
-Alice initializes counter c
which is unique to Bob and increments with each transaction. c
is a 64-bit integer and must be inputted into a hasher as a big-endian encoded array of 8 bytes.
+Alice initializes counter ''c'' which is unique to Bob and increments with each transaction. ''c'' is a 64-bit integer and must be inputted into a hasher as a big-endian encoded array of 8 bytes.
1. Alice calculates a secret point (constant between Alice and Bob):
-
-S = n_x * P
-
+''S = nx * P''
2. Alice calculates a shared secret:
-
-s = SHA256(S, c)
-
+''s = H(S | c)''
3. Alice calculates Bob's ephemeral public key and its associated address where the funds will be sent:
-
-P_c = P + s*G
-
+''Pc = P + s*G''
-4. Alice constructs an address using the key P_c
, using one of the address types she committed to in the notification transaction.
+4. Alice constructs an address using the key ''Pc'', using one of the address types she committed to in the notification transaction.
-Bob constructs his watchlist by mirroring this process on his end, except that his method of calculating S is:
+Bob constructs his watchlist by mirroring this process on his end, except that his method of calculating ''S'' is:
-
-S = N_x * p
-
+''S = Nx * p''
When Bob wants to spend from such addresses, he calculates his private keys in the following manner:
-
-p_c = p + s
-
+''pc = p + s''
==Test Vectors==
@@ -180,9 +171,9 @@ p_c = p + s
'''x:''' 0
-'''n_x:''' 011447e7c6426aecd3fb3e76fba39ef3dc1e91dc578e8b535f714234c62675c5
+'''nx:''' 011447e7c6426aecd3fb3e76fba39ef3dc1e91dc578e8b535f714234c62675c5
-'''N_x:''' 039d138aaf5bc2e27a9740541576eceb90a5f20b4799dbfda48e5c7ca240505753
+'''Nx:''' 039d138aaf5bc2e27a9740541576eceb90a5f20b4799dbfda48e5c7ca240505753
===Bob's Wallet===
@@ -216,15 +207,15 @@ p_c = p + s
'''s*G:''' 0x03e99301fb24083590fde78473d55a8435b0aed0dad65c516dfb268586fbe134be
-'''P_c:''' 0x03145adc275eda50ea188250f85e729b77b22f9868d024aff00ea61d552373cbba
+'''Pc:''' 0x03145adc275eda50ea188250f85e729b77b22f9868d024aff00ea61d552373cbba
-'''A_c:''' bc1q7nmrkdgg3qq3l2ggh46zwv7750q6rjux0nx27a
+'''Ac:''' bc1q7nmrkdgg3qq3l2ggh46zwv7750q6rjux0nx27a
===Bob spending===
'''c:''' 0
-'''p_c:''' 0xf2f9c44c15a0b9f3590ab36e6324ab781b12e3f40abc745611d06a46894aab88
+'''pc:''' 0xf2f9c44c15a0b9f3590ab36e6324ab781b12e3f40abc745611d06a46894aab88
==Reference==
* [[bip-0032.mediawiki|BIP32 - Hierarchical Deterministic Wallets]]
--
cgit v1.2.3
From 947916e5ba2e572c61ea0b323e87035c7f49c057 Mon Sep 17 00:00:00 2001
From: Alfred Hodler <100861939+alfred-hodler@users.noreply.github.com>
Date: Tue, 26 Jul 2022 17:51:09 +0000
Subject: Update wording
---
bip-alfredhodler-privatepayments.mediawiki | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/bip-alfredhodler-privatepayments.mediawiki b/bip-alfredhodler-privatepayments.mediawiki
index f99ce60..9673825 100644
--- a/bip-alfredhodler-privatepayments.mediawiki
+++ b/bip-alfredhodler-privatepayments.mediawiki
@@ -35,7 +35,7 @@ A recipient that wishes to receive funds privately has several options. Each has
==Method==
-When Alice wants to start paying Bob in private, she imports his payment code into a compatible wallet. Her wallet extracts Bob's public key from the payment code, constructs a notification transaction and sends it to a static address that all users of this BIP watch. If Bob finds a notification transaction addressed to himself, he imports Alice's public key contained therein and stores it. Bob then performs ECDH using Alice's public key and his own private key in order to calculate a common set of addresses to watch. Alice calculates the same set of addresses on her end and uses them to send coins to Bob. If Alice engages in coin control, both the initial notification transaction and subsequent payment transactions cannot be attributed to either party. Even if Alice uses coins that are already associated with her, chain analysis will identify her as a sender but Bob's privacy will remain entirely preserved.
+When Alice wants to start paying Bob in private, she imports his payment code into a compatible wallet. Her wallet extracts Bob's public key from the payment code and sends a notification transaction. If Bob finds a notification transaction addressed to himself, he imports Alice's public key contained therein and stores it. Bob then performs ECDH using Alice's public key and his own private key in order to calculate a common set of addresses to watch. Alice calculates the same set of addresses on her end and uses them to send coins to Bob. If Alice engages in coin control, both the initial notification transaction and subsequent payment transactions cannot be attributed to either party. Even if Alice uses coins that are already associated with her, chain analysis will identify her as a sender but Bob's privacy will remain entirely preserved.
==Specification==
@@ -103,7 +103,7 @@ While payment codes use 2-byte bitflag arrays, notifications use ordinal values
===Notifications===
-Notifications are performed by publishing transactions that contain a single 72-byte OP_RETURN
output. The value of the OP_RETURN
is constructed using the following formula:
+Notifications are performed by publishing transactions that contain a 72-byte OP_RETURN
output. The value of the OP_RETURN
is constructed using the following formula:
''search_key | notification_code | Nx | address_type''
--
cgit v1.2.3
From 9caa27ccd444b7259289adf2a1cce059e5d932aa Mon Sep 17 00:00:00 2001
From: Clark Moody
Date: Fri, 29 Jul 2022 12:10:58 -0500
Subject: Two potential third-party services
---
bip-alfredhodler-privatepayments.mediawiki | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/bip-alfredhodler-privatepayments.mediawiki b/bip-alfredhodler-privatepayments.mediawiki
index 9673825..bb411d2 100644
--- a/bip-alfredhodler-privatepayments.mediawiki
+++ b/bip-alfredhodler-privatepayments.mediawiki
@@ -157,7 +157,7 @@ When Bob wants to spend from such addresses, he calculates his private keys in t
''pc = p + s''
-==Test Vectors==
+==Appendix A: Test Vectors==
===Alice's Wallet===
@@ -217,6 +217,16 @@ When Bob wants to spend from such addresses, he calculates his private keys in t
'''pc:''' 0xf2f9c44c15a0b9f3590ab36e6324ab781b12e3f40abc745611d06a46894aab88
+==Appendix B: Potential OP_RUTURN Services==
+
+Compact Block Filters, as formulated in BIP-0158, do not cover OP_RETURN
data payloads. In support of light wallets, an external service could publish transaction proofs for all transactions that include the tagged notification payload. Light wallets would download all such transactions, filter for matches against their payment code, then verify the transaction proofs against the block headers obtained over the P2P network.
+
+==Appendix C: Potential Notification Transaction Services==
+
+No specific instruction is given as to the details of the notification transaction beyond simply including the single OP_RETURN
payload. Since no restriction exists for other inputs or outputs of this transaction, there is an opportunity for an external service to include this payload in a transaction completely unrelated to Alice's wallet. Such a service could charge a fee out-of-band to help cover fees.
+
+Another opportunity exists for an existing business to attach notification payloads to transactions sent during the normal course of operations. Large withdrawal transactions from mining pools or exchanges could include a marginal notification payload without affecting overall fees.
+
==Reference==
* [[bip-0032.mediawiki|BIP32 - Hierarchical Deterministic Wallets]]
* [[bip-0043.mediawiki|BIP43 - Purpose Field for Deterministic Wallets]]
--
cgit v1.2.3
From df9830a855ecba438926172e79832bbdf13d584b Mon Sep 17 00:00:00 2001
From: Clark Moody
Date: Fri, 29 Jul 2022 12:11:08 -0500
Subject: Update authors list
---
bip-alfredhodler-privatepayments.mediawiki | 1 +
1 file changed, 1 insertion(+)
diff --git a/bip-alfredhodler-privatepayments.mediawiki b/bip-alfredhodler-privatepayments.mediawiki
index bb411d2..981de42 100644
--- a/bip-alfredhodler-privatepayments.mediawiki
+++ b/bip-alfredhodler-privatepayments.mediawiki
@@ -3,6 +3,7 @@
Layer: Applications
Title: Private Payments
Author: Alfred Hodler
+ Clark Moody
Status: Draft
Type: Informational
Created: 2022-07-10
--
cgit v1.2.3
From 063d70219a6268b20578d8e7d8b81ae67bc07721 Mon Sep 17 00:00:00 2001
From: Alfred Hodler <100861939+alfred-hodler@users.noreply.github.com>
Date: Sat, 30 Jul 2022 08:45:48 +0000
Subject: Improve wording
---
bip-alfredhodler-privatepayments.mediawiki | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/bip-alfredhodler-privatepayments.mediawiki b/bip-alfredhodler-privatepayments.mediawiki
index 981de42..b5f028a 100644
--- a/bip-alfredhodler-privatepayments.mediawiki
+++ b/bip-alfredhodler-privatepayments.mediawiki
@@ -120,7 +120,7 @@ When Alice wants to notify Bob that he will receive future payments from her, sh
# Commits to one of Bob's accepted address types by choosing its ordinal value. Going forward Alice must not send to address types other than the one she committed to in the notification.
# Constructs a notification payload by concatenating the above values according to the formula.
# Selects any UTXO in her wallet, preferably not associated with her.
-# Sends a transaction with a single OP_RETURN
output whose value is set to the constructed payload.
+# Sends a transaction including an OP_RETURN
output whose value is set to the constructed payload.
When Bob notices an OP_RETURN
starting with the search key, he performs the following procedure:
@@ -218,7 +218,7 @@ When Bob wants to spend from such addresses, he calculates his private keys in t
'''pc:''' 0xf2f9c44c15a0b9f3590ab36e6324ab781b12e3f40abc745611d06a46894aab88
-==Appendix B: Potential OP_RUTURN Services==
+==Appendix B: Potential OP_RETURN Services==
Compact Block Filters, as formulated in BIP-0158, do not cover OP_RETURN
data payloads. In support of light wallets, an external service could publish transaction proofs for all transactions that include the tagged notification payload. Light wallets would download all such transactions, filter for matches against their payment code, then verify the transaction proofs against the block headers obtained over the P2P network.
--
cgit v1.2.3
From 73304846804651608bde30237592d7ae04c029a6 Mon Sep 17 00:00:00 2001
From: Alfred Hodler <100861939+alfred-hodler@users.noreply.github.com>
Date: Mon, 1 Aug 2022 11:00:01 +0000
Subject: Incorporate feedback
---
bip-alfredhodler-privatepayments.mediawiki | 29 ++++++++++++++++++++---------
1 file changed, 20 insertions(+), 9 deletions(-)
diff --git a/bip-alfredhodler-privatepayments.mediawiki b/bip-alfredhodler-privatepayments.mediawiki
index b5f028a..aef0d80 100644
--- a/bip-alfredhodler-privatepayments.mediawiki
+++ b/bip-alfredhodler-privatepayments.mediawiki
@@ -4,6 +4,7 @@
Title: Private Payments
Author: Alfred Hodler
Clark Moody
+ Ruben Somsen
Status: Draft
Type: Informational
Created: 2022-07-10
@@ -60,6 +61,7 @@ When Alice wants to start paying Bob in private, she imports his payment code in
* ''*'': EC multiplication
* ''+'': EC addition
* ''|'': string concatenation
+* ''[a..b]'': string slicing (inclusive of ''a'', exclusive of ''b'')
===Public Key Derivation Path===
@@ -77,8 +79,8 @@ m / purpose' / coin_type' / account'
===Payment Code Structure and Encoding===
-* bytes [0..1]
: address type flags (2 bytes, inclusive)
-* bytes [2..35]
: compressed public key P (33 bytes, inclusive)
+* bytes [0..2]
: address type flags (2 bytes)
+* bytes [2..36]
: compressed public key P (33 bytes)
Payment codes are encoded in bech32m and the human readable part is "pay" for mainnet and "payt" for testnet (all types), resulting in payment codes that look like "pay1cqqq8d29g0a7m8ghmycqk5yv24mfh3xg8ptzqcn8xz6d2tjl8ccdnfkpjl7p84".
@@ -104,19 +106,19 @@ While payment codes use 2-byte bitflag arrays, notifications use ordinal values
===Notifications===
-Notifications are performed by publishing transactions that contain a 72-byte OP_RETURN
output. The value of the OP_RETURN
is constructed using the following formula:
+Notifications are performed by publishing transactions that contain a 44-byte OP_RETURN
output. The value of the OP_RETURN
is constructed using the following formula:
''search_key | notification_code | Nx | address_type''
* ''search_key'' equals "BIP999" and is a static ASCII-encoded string (6 bytes)
-* ''notification_code'' is ''H(nx * P)'' (32 bytes)
+* ''notification_code'' is ''H(nx * P)[0..4]'' (4 bytes)
* ''Nx'' is the unique public key a sender is using for a particular recipient (33 bytes)
* ''address_type'' is the '''ordinal''' value of a single address type that a sender wants to send to (1 byte). This must be selected from the recepient's accepted address types.
When Alice wants to notify Bob that he will receive future payments from her, she performs the following procedure:
# Assigns an unused, unique index ''x'' to Bob (''0'' if Bob is the first party she is notifying).
-# Calculates a notification code: ''notification_code = H(nx * P)''
+# Calculates a 4-byte notification code: ''notification_code = H(nx * P)[0..4]''
# Commits to one of Bob's accepted address types by choosing its ordinal value. Going forward Alice must not send to address types other than the one she committed to in the notification.
# Constructs a notification payload by concatenating the above values according to the formula.
# Selects any UTXO in her wallet, preferably not associated with her.
@@ -126,12 +128,20 @@ When Bob notices an OP_RETURN
starting with the search key, he perf
# Breaks down the payload into its four constituent parts.
# Discards the ''search_key'' (item #0).
-# Selects ''Nx'' (item #2) and performs ''H(Nx * p)'' (Bob does not know the value of ''x'').
-# If the above value matches the notification value (item #1), Bob found a notification addressed to himself and stores ''Nx'' together with ''address_type''.
+# Selects ''Nx'' (item #2) and performs ''H(Nx * p)'' (Bob does not know the value of ''x''). Bob takes the first four bytes of the calculated value.
+# If the four bytes match the notification value (item #1), Bob found a notification addressed to himself and stores ''Nx'' together with ''address_type''.
# If this process fails for any reason, Bob assumes a spurious notification or one not addressed to himself and gives up.
Since changing ''x'' yields a completely different sender identity, Alice can always re-notify Bob from a different index when she does not want to be associated with her previous identity. Alice can also re-notify Bob when she wants to start sending to a different address type. Bob must be able to update his watchlist in that case and he can stop watching addresses associated with the old address type.
+===Allowing Notification Collisions===
+
+Since ''notification_code'' is a 4-byte truncation of the full value, Bob has a 1 in ~4.3 billion chance of detecting a spurious notification. This is considered acceptable because the cost of doing so is adding a few more addresses to Bob's watchlist. The benefit of this approach is that is saves 28 bytes per notification.
+
+===Scanning Requirement===
+
+There is a scanning requirement on the recipient side in that the recipient must have access to full blocks in order to be able to search them for OP_RETURN outputs containing notifications. For more information on how light clients can get around this limitation and still use the standard, see Appendix B.
+
===Transacting===
Alice initializes counter ''c'' which is unique to Bob and increments with each transaction. ''c'' is a 64-bit integer and must be inputted into a hasher as a big-endian encoded array of 8 bytes.
@@ -194,11 +204,11 @@ When Bob wants to spend from such addresses, he calculates his private keys in t
===Alice notifying Bob===
'''S:''' 0x0295ac9a667d7077def44b11104811e5d91d164dd60cb08275b313a33691320cb3
-'''Notification code:''' 0xfbe8d683683023aaa066ba13cf79c9f8a7d3c69a4705025f3f4f4887a61eb975
+'''Notification code:''' 0xfbe8d683
'''Address type commitment:''' 1 (segwit)
-'''Notification output script:''' OP_RETURN OP_PUSHBYTES_72 424950393939fbe8d683683023aaa066ba13cf79c9f8a7d3c69a4705025f3f4f4887a61eb975039d138aaf5bc2e27a9740541576eceb90a5f20b4799dbfda48e5c7ca24050575301
+'''Notification output script:''' OP_RETURN OP_PUSHBYTES_44 424950393939fbe8d683039d138aaf5bc2e27a9740541576eceb90a5f20b4799dbfda48e5c7ca24050575301
===Alice sending to Bob===
@@ -218,6 +228,7 @@ When Bob wants to spend from such addresses, he calculates his private keys in t
'''pc:''' 0xf2f9c44c15a0b9f3590ab36e6324ab781b12e3f40abc745611d06a46894aab88
+
==Appendix B: Potential OP_RETURN Services==
Compact Block Filters, as formulated in BIP-0158, do not cover OP_RETURN
data payloads. In support of light wallets, an external service could publish transaction proofs for all transactions that include the tagged notification payload. Light wallets would download all such transactions, filter for matches against their payment code, then verify the transaction proofs against the block headers obtained over the P2P network.
--
cgit v1.2.3
From 50e707bd8c6ed36f36ea3c8447f043dee5c2a0f9 Mon Sep 17 00:00:00 2001
From: Alfred Hodler <100861939+alfred-hodler@users.noreply.github.com>
Date: Mon, 1 Aug 2022 12:15:46 +0000
Subject: Leaner notifications
---
bip-alfredhodler-privatepayments.mediawiki | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/bip-alfredhodler-privatepayments.mediawiki b/bip-alfredhodler-privatepayments.mediawiki
index aef0d80..159d427 100644
--- a/bip-alfredhodler-privatepayments.mediawiki
+++ b/bip-alfredhodler-privatepayments.mediawiki
@@ -106,11 +106,11 @@ While payment codes use 2-byte bitflag arrays, notifications use ordinal values
===Notifications===
-Notifications are performed by publishing transactions that contain a 44-byte OP_RETURN
output. The value of the OP_RETURN
is constructed using the following formula:
+Notifications are performed by publishing transactions that contain a 40-byte OP_RETURN
output. The value of the OP_RETURN
is constructed using the following formula:
''search_key | notification_code | Nx | address_type''
-* ''search_key'' equals "BIP999" and is a static ASCII-encoded string (6 bytes)
+* ''search_key'' equals "PP" and is a static ASCII-encoded string (2 bytes)
* ''notification_code'' is ''H(nx * P)[0..4]'' (4 bytes)
* ''Nx'' is the unique public key a sender is using for a particular recipient (33 bytes)
* ''address_type'' is the '''ordinal''' value of a single address type that a sender wants to send to (1 byte). This must be selected from the recepient's accepted address types.
@@ -124,7 +124,7 @@ When Alice wants to notify Bob that he will receive future payments from her, sh
# Selects any UTXO in her wallet, preferably not associated with her.
# Sends a transaction including an OP_RETURN
output whose value is set to the constructed payload.
-When Bob notices an OP_RETURN
starting with the search key, he performs the following procedure:
+When Bob notices a 40-byte OP_RETURN
starting with ''search key'', he performs the following procedure:
# Breaks down the payload into its four constituent parts.
# Discards the ''search_key'' (item #0).
@@ -142,6 +142,8 @@ Since ''notification_code'' is a 4-byte truncation of the full value, Bob has a
There is a scanning requirement on the recipient side in that the recipient must have access to full blocks in order to be able to search them for OP_RETURN outputs containing notifications. For more information on how light clients can get around this limitation and still use the standard, see Appendix B.
+Recipients that do not want to decode raw block data can quickly search for notifications in a block by looking for the following byte array: [106, 40, 80, 80]
. The first two bytes represent ''OP_RETURN'' and ''OP_PUSHBYTES_40'', followed by the ASCII value of ''search_key''.
+
===Transacting===
Alice initializes counter ''c'' which is unique to Bob and increments with each transaction. ''c'' is a 64-bit integer and must be inputted into a hasher as a big-endian encoded array of 8 bytes.
@@ -208,7 +210,7 @@ When Bob wants to spend from such addresses, he calculates his private keys in t
'''Address type commitment:''' 1 (segwit)
-'''Notification output script:''' OP_RETURN OP_PUSHBYTES_44 424950393939fbe8d683039d138aaf5bc2e27a9740541576eceb90a5f20b4799dbfda48e5c7ca24050575301
+'''Notification output script:''' OP_RETURN OP_PUSHBYTES_40 5050fbe8d683039d138aaf5bc2e27a9740541576eceb90a5f20b4799dbfda48e5c7ca24050575301
===Alice sending to Bob===
--
cgit v1.2.3
From c053962759475be1e0564eca836166e2fff062eb Mon Sep 17 00:00:00 2001
From: pox <47615825+pox@users.noreply.github.com>
Date: Sun, 31 Jul 2022 08:20:11 +0100
Subject: added reference to BIP 47
---
bip-alfredhodler-privatepayments.mediawiki | 1 +
1 file changed, 1 insertion(+)
diff --git a/bip-alfredhodler-privatepayments.mediawiki b/bip-alfredhodler-privatepayments.mediawiki
index 159d427..86ea2a4 100644
--- a/bip-alfredhodler-privatepayments.mediawiki
+++ b/bip-alfredhodler-privatepayments.mediawiki
@@ -245,6 +245,7 @@ Another opportunity exists for an existing business to attach notification paylo
* [[bip-0032.mediawiki|BIP32 - Hierarchical Deterministic Wallets]]
* [[bip-0043.mediawiki|BIP43 - Purpose Field for Deterministic Wallets]]
* [[bip-0044.mediawiki|BIP44 - Multi-Account Hierarchy for Deterministic Wallets]]
+* [[bip-0047.mediawiki|BIP47 - Reusable Payment Codes for Hierarchical Deterministic Wallets]]
* [[bip-0157.mediawiki|BIP157 - Client Side Block Filtering]]
* [[bip-0158.mediawiki|BIP158 - Compact Block Filters for Light Clients]]
--
cgit v1.2.3
From 187135c4f6e60b63bf025419c6eb117c0a1b18cd Mon Sep 17 00:00:00 2001
From: Alfred Hodler <100861939+alfred-hodler@users.noreply.github.com>
Date: Fri, 19 Aug 2022 10:14:32 +0000
Subject: Updates to the BIP
- fix out of range indexing
- add a note about compressed keys
- add a note about of-of-band notifications
- add a backward compatibility section
---
bip-alfredhodler-privatepayments.mediawiki | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/bip-alfredhodler-privatepayments.mediawiki b/bip-alfredhodler-privatepayments.mediawiki
index 86ea2a4..05079e0 100644
--- a/bip-alfredhodler-privatepayments.mediawiki
+++ b/bip-alfredhodler-privatepayments.mediawiki
@@ -80,7 +80,7 @@ m / purpose' / coin_type' / account'
===Payment Code Structure and Encoding===
* bytes [0..2]
: address type flags (2 bytes)
-* bytes [2..36]
: compressed public key P (33 bytes)
+* bytes [2..35]
: compressed public key P (33 bytes)
Payment codes are encoded in bech32m and the human readable part is "pay" for mainnet and "payt" for testnet (all types), resulting in payment codes that look like "pay1cqqq8d29g0a7m8ghmycqk5yv24mfh3xg8ptzqcn8xz6d2tjl8ccdnfkpjl7p84".
@@ -104,6 +104,8 @@ The remaining flags are reserved for future address types.
While payment codes use 2-byte bitflag arrays, notifications use ordinal values in the form of a single byte.
+All keys are compressed. Using uncompressed keys at any point is illegal.
+
===Notifications===
Notifications are performed by publishing transactions that contain a 40-byte OP_RETURN
output. The value of the OP_RETURN
is constructed using the following formula:
@@ -134,6 +136,8 @@ When Bob notices a 40-byte OP_RETURN
starting with ''search key'',
Since changing ''x'' yields a completely different sender identity, Alice can always re-notify Bob from a different index when she does not want to be associated with her previous identity. Alice can also re-notify Bob when she wants to start sending to a different address type. Bob must be able to update his watchlist in that case and he can stop watching addresses associated with the old address type.
+Out-of-band notifications between Alice and Bob are legal (in fact, they may not be prevented), but in that case Bob loses the ability to restore his wallet from OP_RETURN
outputs embedded in the blockchain. In that case, Bob has the burden of keeping a valid backup of any out-of-band notifications.
+
===Allowing Notification Collisions===
Since ''notification_code'' is a 4-byte truncation of the full value, Bob has a 1 in ~4.3 billion chance of detecting a spurious notification. This is considered acceptable because the cost of doing so is adding a few more addresses to Bob's watchlist. The benefit of this approach is that is saves 28 bytes per notification.
@@ -170,6 +174,12 @@ When Bob wants to spend from such addresses, he calculates his private keys in t
''pc = p + s''
+==Backward Compatibility==
+
+Private Payments is a new standard which is not compatible with any previous standard based on static payment codes, such as BIP47.
+
+While the standard does not support versioning, it reserves unused bits in the address type bitflag array which can be allocated to new address types once they are deemed ubiquitous. Older payment codes (i.e. those generated when fewer address types were available) are readable by software supporting new address types. The reverse is also supported since older software will ignore newer address type flags that are not understood.
+
==Appendix A: Test Vectors==
===Alice's Wallet===
--
cgit v1.2.3
From 75a6f21e3a641f930c0c5802264797fa7acd1002 Mon Sep 17 00:00:00 2001
From: Alfred Hodler
Date: Mon, 22 Aug 2022 08:53:42 +0000
Subject: Update BIP number and test vectors
---
bip-alfredhodler-privatepayments.mediawiki | 37 ++++++++++++++----------------
1 file changed, 17 insertions(+), 20 deletions(-)
diff --git a/bip-alfredhodler-privatepayments.mediawiki b/bip-alfredhodler-privatepayments.mediawiki
index 05079e0..02c45ad 100644
--- a/bip-alfredhodler-privatepayments.mediawiki
+++ b/bip-alfredhodler-privatepayments.mediawiki
@@ -1,5 +1,5 @@
- BIP: ?
+ BIP: 351
Layer: Applications
Title: Private Payments
Author: Alfred Hodler
@@ -11,8 +11,6 @@
License: MIT
-In the following text the BIP number is provisionally set to 999 for technical purposes until a BIP number is assigned.
-
==Abstract==
This BIP makes it possible for two parties to transact using addresses that only they can calculate. This is done using exclusively on-chain methods and in a manner that minimizes blockchain footprint. Receiving parties can share their payment codes publicly without a loss of privacy, as every sender will calculate a unique set of addresses for each payment code.
@@ -71,7 +69,7 @@ The derivation path for this BIP follows BIP44. The following BIP32 path levels
m / purpose' / coin_type' / account'
-purpose
is set to 999.
+purpose
is set to 351.
''(p, P)'' and ''(n, N)'' are keys associated with the above path, depending on which side is performing the calculation.
@@ -188,15 +186,15 @@ While the standard does not support versioning, it reserves unused bits in the a
'''Master xprv:''' xprv9s21ZrQH143K2qVytoy3eZSSuc1gfzFrkV4bgoHzYTkgge4UoNP62eV8jkHYNqddaaefpnjwkz71P5m4EW6RuQBJeP9pdfa9WBnjP6XUivG
-'''n:''' xprv9xgkGJLpRhrdGVTFqS49xKyH85yUKWfkazSjWUbnaqmRf5ucc2YwruLmFwqwtZ3S3Whxgj52HoyTrtfbzDUrAseWmER9DK3TZUTorzSpkdt
+'''n:''' xprv9zNFGn56Wm1s89ycTCg4hB615ehu6ZvNL4mxUEAL28pNhBAb6SZgLdsgmQd1ECgAiCjy6XxTTRyBdPAhH1oMfLhv2bSwfiCYhL9s9ahEehf
-'''N:''' xpub6Bg6fosiG5QvUyXiwTbAKTv1g7oxiyPbxDNLJs1Q9BJQXtEm9ZsCQhfF7CEo94MBjwEz5wBmCuo5AcSeBtKDE73GfGcQ6PATzVBVfdPtY17
+'''N:''' xpub6DMbgHbzM8aALe45ZED54K2jdgYPW2eDhHhZGcZwaUMMZyVjdysvtSCAcfPYiqB5Zw41EyLWPxCXko6iEckwRdF5CD2ZKdTxUKigPXsnpaE
'''x:''' 0
-'''nx:''' 011447e7c6426aecd3fb3e76fba39ef3dc1e91dc578e8b535f714234c62675c5
+'''nx:''' be9518016ec15762877de7d2ce7367a2087cf5682e72bbffa89535d73bb42f40
-'''Nx:''' 039d138aaf5bc2e27a9740541576eceb90a5f20b4799dbfda48e5c7ca240505753
+'''Nx:''' 02e3217349724307eed5514b53b1f53f0802672a9913d9bbb76afecc86be23f464
===Bob's Wallet===
@@ -204,42 +202,41 @@ While the standard does not support versioning, it reserves unused bits in the a
'''Master xprv:''' xprv9s21ZrQH143K47bRNtc26e8Gb3wkUiJ4fH3ewYgJeiGABp7vQtTKsLBzHM2fsfiK7Er6uMrWbdDwwrdcVn5TDC1T1npTFFkdEVoMgTwfVuR
-'''p:''' 0x3ba93579cf5b37d18cd2e3507d51b22c3771a2dbfd1b58dd45d08a6e6ed4b965
+'''p:''' 0x26c610e7d0ed4395be3f0664073d66b0a3442b49e1ec13faf2dd9b7d3c335441
-'''P:''' 0x02943ebcb1dbb1e1cb7c0350687c2c8dbdf1c4f350d849341a6ff61a595f2085e2
+'''P:''' 0x0302be8bff520f35fae3439f245c52afb9085a7bf62d099c1f5e9e1b15a7e2121a
'''Accepted scripts:''' 0x03 (legacy + segwit) (0x01 | 0x02)
-'''Payment code:''' pay1qqps99p7hjcahv0ped7qx5rg0skgm003cne4pkzfxsdxlas6t90jpp0zpnwgqy
+'''Payment code:''' pay1qqpsxq4730l4yre4lt3588eyt3f2lwggtfalvtgfns04a8smzkn7yys6xv2gs8
===Alice notifying Bob===
-'''S:''' 0x0295ac9a667d7077def44b11104811e5d91d164dd60cb08275b313a33691320cb3
+'''S:''' 0x02c0892d6ba30b5b1eafebd47172e46d358721f294698f9f59b4d96b781da09a62
-'''Notification code:''' 0xfbe8d683
+'''Notification code:''' 0x49cb55bb
'''Address type commitment:''' 1 (segwit)
-'''Notification output script:''' OP_RETURN OP_PUSHBYTES_40 5050fbe8d683039d138aaf5bc2e27a9740541576eceb90a5f20b4799dbfda48e5c7ca24050575301
+'''Notification output script:''' OP_RETURN OP_PUSHBYTES_40 505049cb55bb02e3217349724307eed5514b53b1f53f0802672a9913d9bbb76afecc86be23f46401
===Alice sending to Bob===
'''c:''' 0
-'''s:''' 0xb7508ed246458221cc37d01de5d2f94be3a141180da11b78cbffdfd81a75f223
+'''s:''' 0x5dbe5efee4a5b9df73708241858f2bf7ec65f141dbd229ea8e2f9f51804a18f2
-'''s*G:''' 0x03e99301fb24083590fde78473d55a8435b0aed0dad65c516dfb268586fbe134be
+'''s*G:''' 0x039362033c1bc3f05e081d4d7f76d5ffebde349b0f6a4d2e8ffc5c065c17233247
-'''Pc:''' 0x03145adc275eda50ea188250f85e729b77b22f9868d024aff00ea61d552373cbba
+'''Pc:''' 0x03e669bd1705691a080840b07d76713d040934a37f2e8dde2fe02f5d3286a49219
-'''Ac:''' bc1q7nmrkdgg3qq3l2ggh46zwv7750q6rjux0nx27a
+'''Ac:''' bc1qw7ld5h9tj2ruwxqvetznjfq9g5jyp0gjhrs30w
===Bob spending===
'''c:''' 0
-'''pc:''' 0xf2f9c44c15a0b9f3590ab36e6324ab781b12e3f40abc745611d06a46894aab88
-
+'''pc:''' 0x84846fe6b592fd7531af88a58ccc92a88faa1c8bbdbe3de5810d3acebc7d6d33
==Appendix B: Potential OP_RETURN Services==
--
cgit v1.2.3
From e56fb64292adabe8412e1d36f869508742de2b3d Mon Sep 17 00:00:00 2001
From: Alfred Hodler + BIP: 351 + Layer: Applications + Title: Private Payments + Author: Alfred Hodler+ +==Abstract== + +This BIP makes it possible for two parties to transact using addresses that only they can calculate. This is done using exclusively on-chain methods and in a manner that minimizes blockchain footprint. Receiving parties can share their payment codes publicly without a loss of privacy, as every sender will calculate a unique set of addresses for each payment code. + +==Motivation== + +A recipient that wishes to receive funds privately has several options. Each has tradeoffs in terms of chain analysis potential, recoverability, and wallet complexity. + +'''Sharing a static address''' works well enough for one-time payments between two parties as long as the address is shared through a private channel. It does not work well for recurring payments because address reuse leads to a loss of privacy. Using this method for donations exacerbates the problem since the address will serve as a focal point for data collection and analysis. Wallets must not reissue the same address to multiple recipients. + +'''Sharing a BIP32 extended public key''' works for recurring payments between two parties only. The same key cannot be shared to any other party without leaking the chain of payments. Furthermore, an extended public key does not say anything about address types and makes it possible for a sender to send to a script that a recipient cannot spend from. Alternate [https://github.com/satoshilabs/slips/blob/master/slip-0132.md version bytes] have been proposed to specify address types, but wallet adoption is limited. + +'''Sharing a BIP380 descriptor containing an extended public key''' solves the address type issue from sharing a raw BIP32 extended key. The drawback is that descriptor support is not widespread, especially in mobile wallets. + +'''Using a payment server''' works in the case of recipients that have the resources to set up and maintain a payment server that will generate a fresh address for each payment. These are usually businesses and the method is usually out of reach for the average user. The centralized server is vulnerable to takedown remotely and physically. + +'''Sharing a BIP47 payment code''' addresses most of the above shortcomings. However, it introduces the following problems: + +* The BIP uses a notification mechanism that relies on publicly known per-recipient notification addresses. If Alice wants to send funds to Bob, she has to use the same notification address that everyone else uses to notify Bob. If Alice is not careful with coin selection, i.e. ensuring that her notification UTXO is not linked to her, she will publicly expose herself as someone who is trying to send funds to Bob and their relationship becomes permanently visible on the blockchain. + +* The BIP does not say anything about address types. Receiving wallets therefore have to watch all address types that can be created from a single public key. Even then, a sender could send to a script that a receipient cannot spend from. + +==Method== + +When Alice wants to start paying Bob in private, she imports his payment code into a compatible wallet. Her wallet extracts Bob's public key from the payment code and sends a notification transaction. If Bob finds a notification transaction addressed to himself, he imports Alice's public key contained therein and stores it. Bob then performs ECDH using Alice's public key and his own private key in order to calculate a common set of addresses to watch. Alice calculates the same set of addresses on her end and uses them to send coins to Bob. If Alice engages in coin control, both the initial notification transaction and subsequent payment transactions cannot be attributed to either party. Even if Alice uses coins that are already associated with her, chain analysis will identify her as a sender but Bob's privacy will remain entirely preserved. + +==Specification== + +===Definitions=== + +* Alice: sender +* Bob: recipient +* Payment code: static string that Bob generates and shares with others so that he can receive payments +* ''P'': public key contained in Bob's payment code +* ''p'': private key associated with Bob's public key ''P'' +* ''N'': extended public key used by Alice to derive child keys for each Bob she wants to transact with +* ''n'': private key associated with Alice's public key ''N'' +* ''x'': Alice's secret recipient index, unique for each Bob +* ''Nx'': child public key derived from ''N'' at index ''x'' (non-hardened) +* ''nx'': private key associated with ''Nx'' +* ''c'': Alice's transaction count toward Bob +* ''Pc'': Bob's public key at index ''c'' +* ''pc'': Bob's private key at index ''c'' +* ''Ac'': Bob's receive address at index ''c'' +* ''H'': SHA256 hash function +* ''*'': EC multiplication +* ''+'': EC addition +* ''|'': string concatenation +* ''[a..b]'': string slicing (inclusive of ''a'', exclusive of ''b'') + +===Public Key Derivation Path=== + +The derivation path for this BIP follows BIP44. The following BIP32 path levels are defined: + ++ Clark Moody + Ruben Somsen + Status: Draft + Type: Informational + Created: 2022-07-10 + License: MIT +
+m / purpose' / coin_type' / account'
+
+
+purpose
is set to 351.
+
+''(p, P)'' and ''(n, N)'' are keys associated with the above path, depending on which side is performing the calculation.
+
+''Nx'' keys are the direct non-hardened children of ''N''. For instance, the path of ''N0'' from ''N'' is ''m / 0''.
+
+===Payment Code Structure and Encoding===
+
+* bytes [0..2]
: address type flags (2 bytes)
+* bytes [2..35]
: compressed public key P (33 bytes)
+
+Payment codes are encoded in bech32m and the human readable part is "pay" for mainnet and "payt" for testnet (all types), resulting in payment codes that look like "pay1cqqq8d29g0a7m8ghmycqk5yv24mfh3xg8ptzqcn8xz6d2tjl8ccdnfkpjl7p84".
+
+===Address Types===
+
+Address type flags determine which address types a payment code accepts. This is represented by big-endian ordered 16 bits. For instance, a hypothetical payment code that handles all address types will have all defined bits set to 1 (0xffff
).
+
+Currently defined flags:
+
+{| class="wikitable"
+! Address Type !! Flag !! Flag Value !! Ordinal Value
+|-
+| P2PKH || 1 << 0
|| 0x0001
|| 0
+|-
+| P2WPKH || 1 << 1
|| 0x0002
|| 1
+|-
+| P2TR || 1 << 2
|| 0x0004
|| 2
+|}
+
+The remaining flags are reserved for future address types.
+
+While payment codes use 2-byte bitflag arrays, notifications use ordinal values in the form of a single byte.
+
+All keys are compressed. Using uncompressed keys at any point is illegal.
+
+===Notifications===
+
+Notifications are performed by publishing transactions that contain a 40-byte OP_RETURN
output. The value of the OP_RETURN
is constructed using the following formula:
+
+''search_key | notification_code | Nx | address_type''
+
+* ''search_key'' equals "PP" and is a static ASCII-encoded string (2 bytes)
+* ''notification_code'' is ''H(nx * P)[0..4]'' (4 bytes)
+* ''Nx'' is the unique public key a sender is using for a particular recipient (33 bytes)
+* ''address_type'' is the '''ordinal''' value of a single address type that a sender wants to send to (1 byte). This must be selected from the recepient's accepted address types.
+
+When Alice wants to notify Bob that he will receive future payments from her, she performs the following procedure:
+
+# Assigns an unused, unique index ''x'' to Bob (''0'' if Bob is the first party she is notifying).
+# Calculates a 4-byte notification code: ''notification_code = H(nx * P)[0..4]''
+# Commits to one of Bob's accepted address types by choosing its ordinal value. Going forward Alice must not send to address types other than the one she committed to in the notification.
+# Constructs a notification payload by concatenating the above values according to the formula.
+# Selects any UTXO in her wallet, preferably not associated with her.
+# Sends a transaction including an OP_RETURN
output whose value is set to the constructed payload.
+
+When Bob notices a 40-byte OP_RETURN
starting with ''search key'', he performs the following procedure:
+
+# Breaks down the payload into its four constituent parts.
+# Discards the ''search_key'' (item #0).
+# Selects ''Nx'' (item #2) and performs ''H(Nx * p)'' (Bob does not know the value of ''x''). Bob takes the first four bytes of the calculated value.
+# If the four bytes match the notification value (item #1), Bob found a notification addressed to himself and stores ''Nx'' together with ''address_type''.
+# If this process fails for any reason, Bob assumes a spurious notification or one not addressed to himself and gives up.
+
+Since changing ''x'' yields a completely different sender identity, Alice can always re-notify Bob from a different index when she does not want to be associated with her previous identity. Alice can also re-notify Bob when she wants to start sending to a different address type. Bob must be able to update his watchlist in that case and he can stop watching addresses associated with the old address type.
+
+Out-of-band notifications between Alice and Bob are legal (in fact, they may not be prevented), but in that case Bob loses the ability to restore his wallet from OP_RETURN
outputs embedded in the blockchain. In that case, Bob has the burden of keeping a valid backup of any out-of-band notifications.
+
+===Allowing Notification Collisions===
+
+Since ''notification_code'' is a 4-byte truncation of the full value, Bob has a 1 in ~4.3 billion chance of detecting a spurious notification. This is considered acceptable because the cost of doing so is adding a few more addresses to Bob's watchlist. The benefit of this approach is that is saves 28 bytes per notification.
+
+===Scanning Requirement===
+
+There is a scanning requirement on the recipient side in that the recipient must have access to full blocks in order to be able to search them for OP_RETURN outputs containing notifications. For more information on how light clients can get around this limitation and still use the standard, see Appendix B.
+
+Recipients that do not want to decode raw block data can quickly search for notifications in a block by looking for the following byte array: [106, 40, 80, 80]
. The first two bytes represent ''OP_RETURN'' and ''OP_PUSHBYTES_40'', followed by the ASCII value of ''search_key''.
+
+===Transacting===
+
+Alice initializes counter ''c'' which is unique to Bob and increments with each transaction. ''c'' is a 64-bit integer and must be inputted into a hasher as a big-endian encoded array of 8 bytes.
+
+1. Alice calculates a secret point (constant between Alice and Bob):
+
+''S = nx * P''
+
+2. Alice calculates a shared secret:
+
+''s = H(S | c)''
+
+3. Alice calculates Bob's ephemeral public key and its associated address where the funds will be sent:
+
+''Pc = P + s*G''
+
+4. Alice constructs an address using the key ''Pc'', using one of the address types she committed to in the notification transaction.
+
+Bob constructs his watchlist by mirroring this process on his end, except that his method of calculating ''S'' is:
+
+''S = Nx * p''
+
+When Bob wants to spend from such addresses, he calculates his private keys in the following manner:
+
+''pc = p + s''
+
+==Backward Compatibility==
+
+Private Payments is a new standard which is not compatible with any previous standard based on static payment codes, such as BIP47.
+
+While the standard does not support versioning, it reserves unused bits in the address type bitflag array which can be allocated to new address types once they are deemed ubiquitous. Older payment codes (i.e. those generated when fewer address types were available) are readable by software supporting new address types. The reverse is also supported since older software will ignore newer address type flags that are not understood.
+
+==Appendix A: Test Vectors==
+
+===Alice's Wallet===
+
+'''BIP32 seed:''' 0xfe
+
+'''Master xprv:''' xprv9s21ZrQH143K2qVytoy3eZSSuc1gfzFrkV4bgoHzYTkgge4UoNP62eV8jkHYNqddaaefpnjwkz71P5m4EW6RuQBJeP9pdfa9WBnjP6XUivG
+
+'''n:''' xprv9zNFGn56Wm1s89ycTCg4hB615ehu6ZvNL4mxUEAL28pNhBAb6SZgLdsgmQd1ECgAiCjy6XxTTRyBdPAhH1oMfLhv2bSwfiCYhL9s9ahEehf
+
+'''N:''' xpub6DMbgHbzM8aALe45ZED54K2jdgYPW2eDhHhZGcZwaUMMZyVjdysvtSCAcfPYiqB5Zw41EyLWPxCXko6iEckwRdF5CD2ZKdTxUKigPXsnpaE
+
+'''x:''' 0
+
+'''nx:''' be9518016ec15762877de7d2ce7367a2087cf5682e72bbffa89535d73bb42f40
+
+'''Nx:''' 02e3217349724307eed5514b53b1f53f0802672a9913d9bbb76afecc86be23f464
+
+
+===Bob's Wallet===
+'''BIP32 seed:''' 0xff
+
+'''Master xprv:''' xprv9s21ZrQH143K47bRNtc26e8Gb3wkUiJ4fH3ewYgJeiGABp7vQtTKsLBzHM2fsfiK7Er6uMrWbdDwwrdcVn5TDC1T1npTFFkdEVoMgTwfVuR
+
+'''p:''' 0x26c610e7d0ed4395be3f0664073d66b0a3442b49e1ec13faf2dd9b7d3c335441
+
+'''P:''' 0x0302be8bff520f35fae3439f245c52afb9085a7bf62d099c1f5e9e1b15a7e2121a
+
+'''Accepted scripts:''' 0x03 (legacy + segwit) (0x01 | 0x02)
+
+'''Payment code:''' pay1qqpsxq4730l4yre4lt3588eyt3f2lwggtfalvtgfns04a8smzkn7yys6xv2gs8
+
+
+===Alice notifying Bob===
+'''S:''' 0x02c0892d6ba30b5b1eafebd47172e46d358721f294698f9f59b4d96b781da09a62
+
+'''Notification code:''' 0x49cb55bb
+
+'''Address type commitment:''' 1 (segwit)
+
+'''Notification output script:''' OP_RETURN OP_PUSHBYTES_40 505049cb55bb02e3217349724307eed5514b53b1f53f0802672a9913d9bbb76afecc86be23f46401
+
+
+===Alice sending to Bob===
+'''c:''' 0
+
+'''s:''' 0x5dbe5efee4a5b9df73708241858f2bf7ec65f141dbd229ea8e2f9f51804a18f2
+
+'''s*G:''' 0x039362033c1bc3f05e081d4d7f76d5ffebde349b0f6a4d2e8ffc5c065c17233247
+
+'''Pc:''' 0x03e669bd1705691a080840b07d76713d040934a37f2e8dde2fe02f5d3286a49219
+
+'''Ac:''' bc1qw7ld5h9tj2ruwxqvetznjfq9g5jyp0gjhrs30w
+
+
+===Bob spending===
+'''c:''' 0
+
+'''pc:''' 0x84846fe6b592fd7531af88a58ccc92a88faa1c8bbdbe3de5810d3acebc7d6d33
+
+==Appendix B: Potential OP_RETURN Services==
+
+Compact Block Filters, as formulated in BIP-0158, do not cover OP_RETURN
data payloads. In support of light wallets, an external service could publish transaction proofs for all transactions that include the tagged notification payload. Light wallets would download all such transactions, filter for matches against their payment code, then verify the transaction proofs against the block headers obtained over the P2P network.
+
+==Appendix C: Potential Notification Transaction Services==
+
+No specific instruction is given as to the details of the notification transaction beyond simply including the single OP_RETURN
payload. Since no restriction exists for other inputs or outputs of this transaction, there is an opportunity for an external service to include this payload in a transaction completely unrelated to Alice's wallet. Such a service could charge a fee out-of-band to help cover fees.
+
+Another opportunity exists for an existing business to attach notification payloads to transactions sent during the normal course of operations. Large withdrawal transactions from mining pools or exchanges could include a marginal notification payload without affecting overall fees.
+
+==Reference==
+* [[bip-0032.mediawiki|BIP32 - Hierarchical Deterministic Wallets]]
+* [[bip-0043.mediawiki|BIP43 - Purpose Field for Deterministic Wallets]]
+* [[bip-0044.mediawiki|BIP44 - Multi-Account Hierarchy for Deterministic Wallets]]
+* [[bip-0047.mediawiki|BIP47 - Reusable Payment Codes for Hierarchical Deterministic Wallets]]
+* [[bip-0157.mediawiki|BIP157 - Client Side Block Filtering]]
+* [[bip-0158.mediawiki|BIP158 - Compact Block Filters for Light Clients]]
+
diff --git a/bip-alfredhodler-privatepayments.mediawiki b/bip-alfredhodler-privatepayments.mediawiki
deleted file mode 100644
index 02c45ad..0000000
--- a/bip-alfredhodler-privatepayments.mediawiki
+++ /dev/null
@@ -1,258 +0,0 @@
-- BIP: 351 - Layer: Applications - Title: Private Payments - Author: Alfred Hodler- -==Abstract== - -This BIP makes it possible for two parties to transact using addresses that only they can calculate. This is done using exclusively on-chain methods and in a manner that minimizes blockchain footprint. Receiving parties can share their payment codes publicly without a loss of privacy, as every sender will calculate a unique set of addresses for each payment code. - -==Motivation== - -A recipient that wishes to receive funds privately has several options. Each has tradeoffs in terms of chain analysis potential, recoverability, and wallet complexity. - -'''Sharing a static address''' works well enough for one-time payments between two parties as long as the address is shared through a private channel. It does not work well for recurring payments because address reuse leads to a loss of privacy. Using this method for donations exacerbates the problem since the address will serve as a focal point for data collection and analysis. Wallets must not reissue the same address to multiple recipients. - -'''Sharing a BIP32 extended public key''' works for recurring payments between two parties only. The same key cannot be shared to any other party without leaking the chain of payments. Furthermore, an extended public key does not say anything about address types and makes it possible for a sender to send to a script that a recipient cannot spend from. Alternate [https://github.com/satoshilabs/slips/blob/master/slip-0132.md version bytes] have been proposed to specify address types, but wallet adoption is limited. - -'''Sharing a BIP380 descriptor containing an extended public key''' solves the address type issue from sharing a raw BIP32 extended key. The drawback is that descriptor support is not widespread, especially in mobile wallets. - -'''Using a payment server''' works in the case of recipients that have the resources to set up and maintain a payment server that will generate a fresh address for each payment. These are usually businesses and the method is usually out of reach for the average user. The centralized server is vulnerable to takedown remotely and physically. - -'''Sharing a BIP47 payment code''' addresses most of the above shortcomings. However, it introduces the following problems: - -* The BIP uses a notification mechanism that relies on publicly known per-recipient notification addresses. If Alice wants to send funds to Bob, she has to use the same notification address that everyone else uses to notify Bob. If Alice is not careful with coin selection, i.e. ensuring that her notification UTXO is not linked to her, she will publicly expose herself as someone who is trying to send funds to Bob and their relationship becomes permanently visible on the blockchain. - -* The BIP does not say anything about address types. Receiving wallets therefore have to watch all address types that can be created from a single public key. Even then, a sender could send to a script that a receipient cannot spend from. - -==Method== - -When Alice wants to start paying Bob in private, she imports his payment code into a compatible wallet. Her wallet extracts Bob's public key from the payment code and sends a notification transaction. If Bob finds a notification transaction addressed to himself, he imports Alice's public key contained therein and stores it. Bob then performs ECDH using Alice's public key and his own private key in order to calculate a common set of addresses to watch. Alice calculates the same set of addresses on her end and uses them to send coins to Bob. If Alice engages in coin control, both the initial notification transaction and subsequent payment transactions cannot be attributed to either party. Even if Alice uses coins that are already associated with her, chain analysis will identify her as a sender but Bob's privacy will remain entirely preserved. - -==Specification== - -===Definitions=== - -* Alice: sender -* Bob: recipient -* Payment code: static string that Bob generates and shares with others so that he can receive payments -* ''P'': public key contained in Bob's payment code -* ''p'': private key associated with Bob's public key ''P'' -* ''N'': extended public key used by Alice to derive child keys for each Bob she wants to transact with -* ''n'': private key associated with Alice's public key ''N'' -* ''x'': Alice's secret recipient index, unique for each Bob -* ''Nx'': child public key derived from ''N'' at index ''x'' (non-hardened) -* ''nx'': private key associated with ''Nx'' -* ''c'': Alice's transaction count toward Bob -* ''Pc'': Bob's public key at index ''c'' -* ''pc'': Bob's private key at index ''c'' -* ''Ac'': Bob's receive address at index ''c'' -* ''H'': SHA256 hash function -* ''*'': EC multiplication -* ''+'': EC addition -* ''|'': string concatenation -* ''[a..b]'': string slicing (inclusive of ''a'', exclusive of ''b'') - -===Public Key Derivation Path=== - -The derivation path for this BIP follows BIP44. The following BIP32 path levels are defined: - -- Clark Moody - Ruben Somsen - Status: Draft - Type: Informational - Created: 2022-07-10 - License: MIT -
-m / purpose' / coin_type' / account'
-
-
-purpose
is set to 351.
-
-''(p, P)'' and ''(n, N)'' are keys associated with the above path, depending on which side is performing the calculation.
-
-''Nx'' keys are the direct non-hardened children of ''N''. For instance, the path of ''N0'' from ''N'' is ''m / 0''.
-
-===Payment Code Structure and Encoding===
-
-* bytes [0..2]
: address type flags (2 bytes)
-* bytes [2..35]
: compressed public key P (33 bytes)
-
-Payment codes are encoded in bech32m and the human readable part is "pay" for mainnet and "payt" for testnet (all types), resulting in payment codes that look like "pay1cqqq8d29g0a7m8ghmycqk5yv24mfh3xg8ptzqcn8xz6d2tjl8ccdnfkpjl7p84".
-
-===Address Types===
-
-Address type flags determine which address types a payment code accepts. This is represented by big-endian ordered 16 bits. For instance, a hypothetical payment code that handles all address types will have all defined bits set to 1 (0xffff
).
-
-Currently defined flags:
-
-{| class="wikitable"
-! Address Type !! Flag !! Flag Value !! Ordinal Value
-|-
-| P2PKH || 1 << 0
|| 0x0001
|| 0
-|-
-| P2WPKH || 1 << 1
|| 0x0002
|| 1
-|-
-| P2TR || 1 << 2
|| 0x0004
|| 2
-|}
-
-The remaining flags are reserved for future address types.
-
-While payment codes use 2-byte bitflag arrays, notifications use ordinal values in the form of a single byte.
-
-All keys are compressed. Using uncompressed keys at any point is illegal.
-
-===Notifications===
-
-Notifications are performed by publishing transactions that contain a 40-byte OP_RETURN
output. The value of the OP_RETURN
is constructed using the following formula:
-
-''search_key | notification_code | Nx | address_type''
-
-* ''search_key'' equals "PP" and is a static ASCII-encoded string (2 bytes)
-* ''notification_code'' is ''H(nx * P)[0..4]'' (4 bytes)
-* ''Nx'' is the unique public key a sender is using for a particular recipient (33 bytes)
-* ''address_type'' is the '''ordinal''' value of a single address type that a sender wants to send to (1 byte). This must be selected from the recepient's accepted address types.
-
-When Alice wants to notify Bob that he will receive future payments from her, she performs the following procedure:
-
-# Assigns an unused, unique index ''x'' to Bob (''0'' if Bob is the first party she is notifying).
-# Calculates a 4-byte notification code: ''notification_code = H(nx * P)[0..4]''
-# Commits to one of Bob's accepted address types by choosing its ordinal value. Going forward Alice must not send to address types other than the one she committed to in the notification.
-# Constructs a notification payload by concatenating the above values according to the formula.
-# Selects any UTXO in her wallet, preferably not associated with her.
-# Sends a transaction including an OP_RETURN
output whose value is set to the constructed payload.
-
-When Bob notices a 40-byte OP_RETURN
starting with ''search key'', he performs the following procedure:
-
-# Breaks down the payload into its four constituent parts.
-# Discards the ''search_key'' (item #0).
-# Selects ''Nx'' (item #2) and performs ''H(Nx * p)'' (Bob does not know the value of ''x''). Bob takes the first four bytes of the calculated value.
-# If the four bytes match the notification value (item #1), Bob found a notification addressed to himself and stores ''Nx'' together with ''address_type''.
-# If this process fails for any reason, Bob assumes a spurious notification or one not addressed to himself and gives up.
-
-Since changing ''x'' yields a completely different sender identity, Alice can always re-notify Bob from a different index when she does not want to be associated with her previous identity. Alice can also re-notify Bob when she wants to start sending to a different address type. Bob must be able to update his watchlist in that case and he can stop watching addresses associated with the old address type.
-
-Out-of-band notifications between Alice and Bob are legal (in fact, they may not be prevented), but in that case Bob loses the ability to restore his wallet from OP_RETURN
outputs embedded in the blockchain. In that case, Bob has the burden of keeping a valid backup of any out-of-band notifications.
-
-===Allowing Notification Collisions===
-
-Since ''notification_code'' is a 4-byte truncation of the full value, Bob has a 1 in ~4.3 billion chance of detecting a spurious notification. This is considered acceptable because the cost of doing so is adding a few more addresses to Bob's watchlist. The benefit of this approach is that is saves 28 bytes per notification.
-
-===Scanning Requirement===
-
-There is a scanning requirement on the recipient side in that the recipient must have access to full blocks in order to be able to search them for OP_RETURN outputs containing notifications. For more information on how light clients can get around this limitation and still use the standard, see Appendix B.
-
-Recipients that do not want to decode raw block data can quickly search for notifications in a block by looking for the following byte array: [106, 40, 80, 80]
. The first two bytes represent ''OP_RETURN'' and ''OP_PUSHBYTES_40'', followed by the ASCII value of ''search_key''.
-
-===Transacting===
-
-Alice initializes counter ''c'' which is unique to Bob and increments with each transaction. ''c'' is a 64-bit integer and must be inputted into a hasher as a big-endian encoded array of 8 bytes.
-
-1. Alice calculates a secret point (constant between Alice and Bob):
-
-''S = nx * P''
-
-2. Alice calculates a shared secret:
-
-''s = H(S | c)''
-
-3. Alice calculates Bob's ephemeral public key and its associated address where the funds will be sent:
-
-''Pc = P + s*G''
-
-4. Alice constructs an address using the key ''Pc'', using one of the address types she committed to in the notification transaction.
-
-Bob constructs his watchlist by mirroring this process on his end, except that his method of calculating ''S'' is:
-
-''S = Nx * p''
-
-When Bob wants to spend from such addresses, he calculates his private keys in the following manner:
-
-''pc = p + s''
-
-==Backward Compatibility==
-
-Private Payments is a new standard which is not compatible with any previous standard based on static payment codes, such as BIP47.
-
-While the standard does not support versioning, it reserves unused bits in the address type bitflag array which can be allocated to new address types once they are deemed ubiquitous. Older payment codes (i.e. those generated when fewer address types were available) are readable by software supporting new address types. The reverse is also supported since older software will ignore newer address type flags that are not understood.
-
-==Appendix A: Test Vectors==
-
-===Alice's Wallet===
-
-'''BIP32 seed:''' 0xfe
-
-'''Master xprv:''' xprv9s21ZrQH143K2qVytoy3eZSSuc1gfzFrkV4bgoHzYTkgge4UoNP62eV8jkHYNqddaaefpnjwkz71P5m4EW6RuQBJeP9pdfa9WBnjP6XUivG
-
-'''n:''' xprv9zNFGn56Wm1s89ycTCg4hB615ehu6ZvNL4mxUEAL28pNhBAb6SZgLdsgmQd1ECgAiCjy6XxTTRyBdPAhH1oMfLhv2bSwfiCYhL9s9ahEehf
-
-'''N:''' xpub6DMbgHbzM8aALe45ZED54K2jdgYPW2eDhHhZGcZwaUMMZyVjdysvtSCAcfPYiqB5Zw41EyLWPxCXko6iEckwRdF5CD2ZKdTxUKigPXsnpaE
-
-'''x:''' 0
-
-'''nx:''' be9518016ec15762877de7d2ce7367a2087cf5682e72bbffa89535d73bb42f40
-
-'''Nx:''' 02e3217349724307eed5514b53b1f53f0802672a9913d9bbb76afecc86be23f464
-
-
-===Bob's Wallet===
-'''BIP32 seed:''' 0xff
-
-'''Master xprv:''' xprv9s21ZrQH143K47bRNtc26e8Gb3wkUiJ4fH3ewYgJeiGABp7vQtTKsLBzHM2fsfiK7Er6uMrWbdDwwrdcVn5TDC1T1npTFFkdEVoMgTwfVuR
-
-'''p:''' 0x26c610e7d0ed4395be3f0664073d66b0a3442b49e1ec13faf2dd9b7d3c335441
-
-'''P:''' 0x0302be8bff520f35fae3439f245c52afb9085a7bf62d099c1f5e9e1b15a7e2121a
-
-'''Accepted scripts:''' 0x03 (legacy + segwit) (0x01 | 0x02)
-
-'''Payment code:''' pay1qqpsxq4730l4yre4lt3588eyt3f2lwggtfalvtgfns04a8smzkn7yys6xv2gs8
-
-
-===Alice notifying Bob===
-'''S:''' 0x02c0892d6ba30b5b1eafebd47172e46d358721f294698f9f59b4d96b781da09a62
-
-'''Notification code:''' 0x49cb55bb
-
-'''Address type commitment:''' 1 (segwit)
-
-'''Notification output script:''' OP_RETURN OP_PUSHBYTES_40 505049cb55bb02e3217349724307eed5514b53b1f53f0802672a9913d9bbb76afecc86be23f46401
-
-
-===Alice sending to Bob===
-'''c:''' 0
-
-'''s:''' 0x5dbe5efee4a5b9df73708241858f2bf7ec65f141dbd229ea8e2f9f51804a18f2
-
-'''s*G:''' 0x039362033c1bc3f05e081d4d7f76d5ffebde349b0f6a4d2e8ffc5c065c17233247
-
-'''Pc:''' 0x03e669bd1705691a080840b07d76713d040934a37f2e8dde2fe02f5d3286a49219
-
-'''Ac:''' bc1qw7ld5h9tj2ruwxqvetznjfq9g5jyp0gjhrs30w
-
-
-===Bob spending===
-'''c:''' 0
-
-'''pc:''' 0x84846fe6b592fd7531af88a58ccc92a88faa1c8bbdbe3de5810d3acebc7d6d33
-
-==Appendix B: Potential OP_RETURN Services==
-
-Compact Block Filters, as formulated in BIP-0158, do not cover OP_RETURN
data payloads. In support of light wallets, an external service could publish transaction proofs for all transactions that include the tagged notification payload. Light wallets would download all such transactions, filter for matches against their payment code, then verify the transaction proofs against the block headers obtained over the P2P network.
-
-==Appendix C: Potential Notification Transaction Services==
-
-No specific instruction is given as to the details of the notification transaction beyond simply including the single OP_RETURN
payload. Since no restriction exists for other inputs or outputs of this transaction, there is an opportunity for an external service to include this payload in a transaction completely unrelated to Alice's wallet. Such a service could charge a fee out-of-band to help cover fees.
-
-Another opportunity exists for an existing business to attach notification payloads to transactions sent during the normal course of operations. Large withdrawal transactions from mining pools or exchanges could include a marginal notification payload without affecting overall fees.
-
-==Reference==
-* [[bip-0032.mediawiki|BIP32 - Hierarchical Deterministic Wallets]]
-* [[bip-0043.mediawiki|BIP43 - Purpose Field for Deterministic Wallets]]
-* [[bip-0044.mediawiki|BIP44 - Multi-Account Hierarchy for Deterministic Wallets]]
-* [[bip-0047.mediawiki|BIP47 - Reusable Payment Codes for Hierarchical Deterministic Wallets]]
-* [[bip-0157.mediawiki|BIP157 - Client Side Block Filtering]]
-* [[bip-0158.mediawiki|BIP158 - Compact Block Filters for Light Clients]]
-
--
cgit v1.2.3
From 1385d65187590f0390c0cb19b82d5272071097df Mon Sep 17 00:00:00 2001
From: Alfred Hodler