Skip to content

Commit cff4d8b

Browse files
authored
Merge pull request #2 from andrewtoth/bip-verifiably-unspendable-key-path
Update specification and add test vectors
2 parents 8201dad + 7a37048 commit cff4d8b

File tree

1 file changed

+50
-13
lines changed

1 file changed

+50
-13
lines changed

bip-xxxx.mediawiki

+50-13
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,59 @@ This document introduces a mechanism to compute a NUMS (Nothing Up My Sleeve) po
2828
2929
==Specification==
3030

31-
A new key expression is defined: <tt>unspendable()</tt>.
31+
A new key expression is defined: <tt>unspendable()/NUM/.../*</tt>.
3232

33-
===<tt>unspendable(KEY, KEY, ..., KEY)</tt>===
33+
===<tt>unspendable()/NUM/.../*</tt>===
3434

35-
The vector of keys is processed in the following sequence: deduplication, compression, sorting, concatenation, and finally, SHA256 hashing to generate a chaincode <tt>r</tt>.
36-
A new unspendable key is constructed by taking the NUMS point <tt>H</tt>, suggested in BIP-0341, and attaching the chaincode <tt>r</tt> we previously computed.
37-
<tt>H + r*G</tt> where <tt>H = lift_x(0x50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0)</tt>
35+
The <tt>unspendable</tt> expression can only be used as the first argument of a BIP386 <tt>tr(KEY, TREE)</tt> expression. All other <tt>KEY</tt> expressions in the descriptor must be <tt>xpub</tt> encoded extended public keys with exactly 2 unhardened derivation steps. The derivation steps may include <tt>/*</tt> or a BIP389 multipath expression, but still must have only unhardened steps. Additionally, BIP390 <tt>musig</tt> expressions are forbidden.
3836

39-
Q: should we add a prefix like the "BIPXXXX" before we SHA256 the keys to ensure the preimage was not previously leaked before this BIP?
40-
Q: is it desireable to specify the keys in the expressions or to extract it from the script expression indirectly?
41-
Q: compress first and then sort, or sort and then compress?
37+
The <tt>unspendable</tt> expression resolves to an extended public key, which is then further derived. As there is no aggregate private key for an unspendable key, only unhardened derivation is allowed.
38+
39+
The extended public key is computed by first collecting the public key from all the extended public keys in all the <tt>KEY</tt> expressions. The collection of public keys then has all duplicates removed and the remaining public keys are sorted lexicographically.
40+
The vector of keys is processed in the following sequence: deduplication, compression, sorting, concatenation, and finally, SHA256 hashing to generate a chaincode <tt>c</tt>.
41+
The unspendable BIP32 extended key is constructed by using the NUMS point <tt>H</tt>, suggested in BIP341, as the public key, and the chaincode <tt>c</tt> is computed as follows:
42+
* The public keys are collected from all extended public keys in all <tt>KEY</tt> expressions.
43+
* All duplicate public keys are removed from the collection and the public keys are sorted lexicographically.
44+
* Let ''P<sub>0</sub> ... P<sub>n</sub>'' be the sorted and deduplicated public keys. Using the notation from BIP340, ''c = hash<sub>BIP0???/chaincode</sub>(bytes(P<sub>0</sub>) || ... || bytes(P<sub>n</sub>))''.
4245
4346
==Test Vectors==
4447

45-
TBD Andew
48+
Valid descriptors containing the <tt>unspendable</tt> expression followed by the chaincode of the unspendable extended public key they expand to and then the scripts they produce.
49+
Todo: These will be filled in when the BIP number is assigned for the tagged hash.
50+
51+
The following produce identical extended public keys and scripts:
52+
* <tt>tr(unspendable()/0, pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/0))</tt>
53+
* <tt>tr(unspendable()/0, pk(xpub661MyMwAqRbcFXsZHGwUFzya6zhjaLUoKt2jKZTsWEoHAPjUERUbW215Fy6DGNLZdNDyMo8WJLgouGNRypxvDFc3MgW8TvRJdpbzsxuyfvr/0/0))</tt>
54+
* <tt>tr(unspendable()/0, pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/<0;1>/*))</tt>
55+
56+
The following has two identical public keys which are deduplicated:
57+
* <tt>tr(unspendable()/0, {pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/0),pk(xpub661MyMwAqRbcFXsZHGwUFzya6zhjaLUoKt2jKZTsWEoHAPjUERUbW215Fy6DGNLZdNDyMo8WJLgouGNRypxvDFc3MgW8TvRJdpbzsxuyfvr/0/0)})</tt>
58+
59+
The following has two identical public keys which are deduplicated, and then the remaining two public keys are sorted:xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw
60+
* <tt>tr(unspendable()/0, {pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/0),{pk(xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw),pk(xpub661MyMwAqRbcFXsZHGwUFzya6zhjaLUoKt2jKZTsWEoHAPjUERUbW215Fy6DGNLZdNDyMo8WJLgouGNRypxvDFc3MgW8TvRJdpbzsxuyfvr/0/0)}})</tt>
61+
62+
Invalid descriptors:
63+
64+
No <tt>TREE</tt> expression:
65+
* <tt>tr(unspendable()/0)</tt>
66+
67+
No derivation path for the unspendable key:
68+
* <tt>tr(unspendable(), pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/0))</tt>
69+
70+
Hardened derivation path for the unspendable key:
71+
* <tt>tr(unspendable()/0'/0, pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/0))</tt>
72+
73+
Hardened derivation path in a <tt>KEY</tt> expression:
74+
* <tt>tr(unspendable()/0, pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0'/0))</tt>
75+
76+
Greater than two derivation paths in a <tt>KEY</tt> expression:
77+
* <tt>tr(unspendable()/0, pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/0/0))</tt>
78+
79+
Less than two derivation paths in a <tt>KEY</tt> expression:
80+
* <tt>tr(unspendable()/0, pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0))</tt>
81+
82+
A <tt>KEY</tt> expression is not an <tt>xpub</tt>:
83+
* <tt>tr(unspendable()/0, pk(0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600))</tt>
4684
4785
==Rationale==
4886

@@ -51,12 +89,11 @@ This proposal ensures:
5189
* Verifiability of unspendable constructions by participants, without exposing this property to outside observers.
5290
* Security and simplicity for signers with limited information (e.g., hardware wallets).
5391
92+
==Backwards Compatibility==
5493

55-
==Reference Implementation==
56-
57-
TBD
94+
This is backwards compatible with BIP386 by computing the unspendable key as a BIP380 <tt>KEY</tt> expression and replacing the <tt>unspendable</tt> expression as the first argument of the <tt>tr()</tt> expression.
5895

5996
==Acknowledgements==
6097

6198
Thanks to Salvatore Ingala, Pieter Wuille, Antoine Poinsot, Andrew Kozlik and all others who
62-
participated in discussions on this topic.
99+
participated in discussions on this topic.

0 commit comments

Comments
 (0)