You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This better matches conventions used in other BIPS.
It's also likely wallet software already has code for doing these
operations if they support BIP32.
Copy file name to clipboardExpand all lines: bip-0000.mediawiki
+8-6Lines changed: 8 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -135,8 +135,10 @@ This gives Bob an alternative to using BIP32 for managing change, while still al
135
135
136
136
We use the following functions and conventions:
137
137
138
-
* ''outpoint'' (36 bytes): the <code>COutPoint</code> of an input (32-byte hash + 4-byte little-endian)
139
-
* ser<sub>32</sub>(i): serializes a 32-bit unsigned integer ''i'' as a 4-byte little-endian
138
+
* ''outpoint'' (36 bytes): the <code>COutPoint</code> of an input (32-byte txid, least significant byte first || 4-byte vout, least significant byte first)<refname="why_little_endian">'''Why are outpoints little-endian?''' Despite using big endian throughout the rest of the BIP, outpoints are sorted and hashed matching their transaction serialization, which is little-endian. This allows a wallet to parse a serialized transaction for use in silent payments without needing to re-order the bytes when compute the outpoint hash. Note: despite outpoints being stored and serialized as little-endian, the transaction hash (txid) is always displayed as big-endian.</ref>
139
+
* ser<sub>32</sub>(i): serializes a 32-bit unsigned integer ''i'' as a 4-byte sequence, most significant byte first.
140
+
* ser<sub>256</sub>(p): serializes the integer p as a 32-byte sequence, most significant byte first.
141
+
* ser<sub>P</sub>(P): serializes the coordinate pair P = (x,y) as a byte sequence using SEC1's compressed form: (0x02 or 0x03) || ser<sub>256</sub>(x), where the header byte depends on the parity of the omitted y coordinate.
140
142
141
143
For everything not defined above, we use the notation from [https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki#specification BIP340].
142
144
@@ -230,10 +232,10 @@ After the inputs have been selected, the sender can create one or more outputs f
230
232
* Generate the ''outpoints_hash'', using the method described above
231
233
* Group receiver silent payment addresses by ''B<sub>scan</sub>'' (e.g. each group consists of one ''B<sub>scan</sub>'' and one or more ''B<sub>m</sub>'')
232
234
* For each group:
233
-
** Let ''ecdh_shared_secret = outpoints_hash·a·B<sub>scan</sub>'', where ''ecdh_shared_secret'' is a compressed public key
235
+
** Let ''ecdh_shared_secret = outpoints_hash·a·B<sub>scan</sub>''
234
236
** Let ''n = 0''
235
237
** For each ''B<sub>m</sub>'' in the group:
236
-
*** Let ''t<sub>n</sub> = sha256(ecdh_shared_secret || ser<sub>32</sub>(n))''
238
+
*** Let ''t<sub>n</sub> = sha256(ser<sub>P</sub>(ecdh_shared_secret) || ser<sub>32</sub>(n))''
237
239
*** Let ''P<sub>mn</sub> = B<sub>m</sub> + t<sub>n</sub>·G''
238
240
*** Encode ''P<sub>mn</sub>'' as a [https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki BIP341] taproot output
239
241
*** Optionally, repeat with n++ to create additional outputs for the current ''B<sub>m</sub>''
@@ -259,11 +261,11 @@ For each transaction the receiving wallet suspects might be a silent payment to
259
261
260
262
* Generate the ''outpoints_hash'', using the method described above
261
263
* Let ''A = A<sub>0</sub> + A<sub>1</sub> + … A<sub>n</sub>'', where each ''A<sub>i</sub>'' is the public key of an input from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list
262
-
* Let ''ecdh_shared_secret = outpoints_hash·b<sub>scan</sub>·A'', where ''ecdh_shared_secret'' is a compressed public key
264
+
* Let ''ecdh_shared_secret = outpoints_hash·b<sub>scan</sub>·A''
263
265
* Check for outputs:
264
266
** Let ''outputs_to_check = the taproot output key from each unspent taproot output in the transaction''
265
267
** Starting with ''n = 0'':
266
-
*** Let ''t<sub>n</sub> = sha256(ecdh_shared_secret || ser<sub>32</sub>(n))''
268
+
*** Let ''t<sub>n</sub> = sha256(ser<sub>P</sub>(ecdh_shared_secret) || ser<sub>32</sub>(n))''
**** If ''P<sub>n</sub>'' is in ''outputs_to_check'', add it to the wallet and continue with ''n++''
269
271
**** If ''P<sub>n</sub>'' is not found and the wallet has precomputed labels<refname="precompute_labels">''' Why precompute labels?''' Naively, a wallet could store some max integer ''M'' which indicates the total number of labels it has used. When checking a transaction, the wallet would need to add all possible labels to each output. This ends up being ''n·m'' additions, where ''n'' is the number of outputs in the transaction and ''m'' is the number of labels in the wallet. By precomputing the labels, the wallet only needs to compute ''m·G'' once per label and can determine if a label was used via a lookup, rather than adding each label to each output.</ref>:
0 commit comments