-
Notifications
You must be signed in to change notification settings - Fork 15
new ELIP: Confidential Transaction descriptors #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
new ELIP: Confidential Transaction descriptors #2
Conversation
elip-ct-descriptors.mediawiki
Outdated
| ==Design== | ||
|
|
||
| ===Overview=== | ||
| We propose a new `ct` descriptor which wraps any other descriptor type in the form `ct(<BLINDING_KEY>, <DESCRIPTOR>)`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
github does not render ct(<BLINDING_KEY>, <DESCRIPTOR>) correctly,
see https://github.com/apoelstra/ELIPs/blob/2022-10--ct-descriptors/elip-ct-descriptors.mediawiki#overview
Also in the "specification" section the bullet points have few rendering issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I see, it's because I'm using MD rather than mediawiki tags. I need to go over the entire doc.
elip-ct-descriptors.mediawiki
Outdated
|
|
||
| However, this has the following drawbacks: | ||
| * The mismatch between "public" keys being used in a "secret" context may lead to user confusion; though we argue this is no worse than the "secret" chaincode value being included in xpubs used by Bitcoin wallets. | ||
| * Any party who has a copy of an addresses' descriptor is able to see the blinding key and unblind coins sent to that address, or *any* derived address in the case of a non-concrete descriptor. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
non-concrete descriptor
What is a "concrete" descriptor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One that is not derived. I should change this to "non-derived" which I think would be clearer.
elip-ct-descriptors.mediawiki
Outdated
| Here `DESCRIPTOR` refers to any existing descriptor, e.g. `wsh(...)` or `tr(...)` and `BLINDING_KEY` is a new expression which must be one of | ||
| * `slip77(<64-character hex>)` which indicates that blinding keys for these addresses are derived via SLIP77; or | ||
| * `hash_to_private(<KEY_1>, <KEY_2>, ...)` which indicates that the blinding key is produced by a hash of the sorted list of one or more public keys; or | ||
| * `<KEY>` which is an ordinary (extended) public key which will be used as a blinding key |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(extended) public key
What do you mean by extended here?
Does this mean we can have xpubs here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it means an xpub.
elip-ct-descriptors.mediawiki
Outdated
|
|
||
| In both the `hash_to_private` and `<KEY>` expressions, all keys must be compressed; x-only and uncompressed keys are invalid. | ||
|
|
||
| We note that even if the descriptor includes private keys, as it will when used for wallet backups, the keys included in the `hash_to_private` combinator will be converted to public keys before sorting and hashing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as it will when used for wallet backups,
nit: This is a bit misleading to me,
why a wallet should include private keys there?
I'm not against allowing to have private keys in hash_to_private,
but I don't understand how setting private keys set in hash_to_private helps the wallet backup and why a wallet should do that.
Anyway this is a nit, so feel free to ignore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bitcoin Core's wallet backups consist of descriptors where every public key slot is filled by a private key. It can also import descriptors of this form, in which case it is able to sign with them.
I agree that in the case of hash_to_private there's no value in making these keys private, since they're never interpreted as private keys. But when dealing with import/export it is easiest if all the keys have the same datatype, which means that all keys, including these, would end up being private ones.
|
@LeoComandini thanks for your review! I have fixed the formatting (I think/hope), and changed the "non-concrete descriptor" text to be clearer. |
dbf2055 to
24098ba
Compare
ccb486e to
ce30581
Compare
elip-ct-descriptors.mediawiki
Outdated
| * <code>slip77(<64-character hex>)</code> which indicates that blinding keys for these addresses are derived via SLIP77; or | ||
| * <code><KEY></code> which is an ordinary (extended) public key; the blinding key is derived by a Taproot-style tweak of the key with the data of <code><DESCRIPTOR></code>. | ||
|
|
||
| In both the <code><KEY></code> expression, all key(s) must be compressed; x-only and uncompressed keys are invalid. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
both
now we have single variant with <KEY>
elip-ct-descriptors.mediawiki
Outdated
| We propose a new <code>ct</code> descriptor which wraps any other descriptor type in the form <code>ct(<BLINDING_KEY>, <DESCRIPTOR>)</code>. | ||
| Here <code>DESCRIPTOR</code> refers to any existing descriptor, e.g. <code>elwsh(...)</code> or <code>eltr(...)</code> and <code>BLINDING_KEY</code> is a new expression which must be one of | ||
| * <code>slip77(<64-character hex>)</code> which indicates that blinding keys for these addresses are derived via SLIP77; or | ||
| * <code><KEY></code> which is an ordinary (extended) public key; the blinding key is derived by a Taproot-style tweak of the key with the data of <code><DESCRIPTOR></code>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extended
Why a wallet should use a xpub/xprv as a bare blinding key?
Now that the key is tweaked with the scriptpubkey (which in most cases should be derived from some xpubs),
I can't think of a reason why a wallet should use xpub/xprv as "master" blinding key rather than a public/private key.
Does it make sense to disallow extended keys for the "bare" variant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. We definitely should support xpubs/xprivs so that they can specify things that have BIP32 paths starting from an existing master seed (otherwise they will need to do a bunch of extra work to derive a public key and then remember how they got it).
I agree that supporting ranged xpubs no longer has a clear utility ... but I see no reason to ban it either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which is an ordinary (extended) public key;
This should probably read something like:
<code><KEY></code> which is an ordinary (or extended) private or public key;
An example bare key with xpub/xprv would be useful in the examples, as would a raw private rather than public key.
I did this in vim with :0,$s/`\(.\{-}\)`/<code>\1<\/code>/g if you want to
reproduce it. Should be easy to review.
Annoyingly mediawiki makes me remove newlines.
9b065a4 to
3d4d49b
Compare
|
Rebased, fixed |
| ** These 32 bytes are the same for both public and private descriptors; they have no "public" equivalent. | ||
| ** This mode is not recommended because there is no way to express this descriptor without revealing the SLIP77 key, which can be used to unblind every single output received by the wallet. | ||
| * '''bare key''', which simply encodes a single key in the same way as the keys in <code><DESCRIPTOR></code> are encoded. The blinding key is derived from the address by taking the public key ''K'' and tweaking it to form a new key ''K<sub>blind</sub>'' as follows: | ||
| ** ''K' = K + H<sub>tag</sub>(K, <code>scriptPubKey</code>)'', where |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be H<sub>tag</sub>(K, <code>scriptPubKey</code>) * G? or K is a private key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, you're right.
elip-ct-descriptors.mediawiki
Outdated
| ** Unconfidential address: <code>ert1pdp6fxh3mq3wtqdtkja2tvsudh9nxy85m67m25agayx92ztz9guvs9wr5lg</code> | ||
| * Invalid Descriptor 1 | ||
| ** <code>ct(slip77(b2396b3ee20509cdb64fe24180a14a72dbd671728eaa49bac69d2bdecb5f5a04),elsh(wpkh(03774eec7a3d550d18e9f89414152025b3b0ad6a342b19481f702d843cff06dfc4)))#xxxxxxxx</code> | ||
| ** Reason: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: missing reason here and below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, I was supposed to fill those in by hand :P
elip-ct-descriptors.mediawiki
Outdated
| ** Blinding key: <code>02dce16018bbbb8e36de7b394df5b5166e9adb7498be7d881a85a09aeecf76b623</code> | ||
| ** Confidential address: <code>AzpsK7uqP1KVEMfDQvBXYUkpHmFagD3W4vaLe1X7uy8MS6nj41kNYnaexuXgx14PcbNnYAqBdCSWcbga</code> | ||
| ** Unconfidential address: <code>XQ7ffnJkhMwj1H8Ma6N1vcU9mqAa96wB9w</code> | ||
| * Valid Descriptor 4: <code>ct(02dce16018bbbb8e36de7b394df5b5166e9adb7498be7d881a85a09aeecf76b623,eltr(03774eec7a3d550d18e9f89414152025b3b0ad6a342b19481f702d843cff06dfc4))#ytq9w7f3</code> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we please have a valid test vector for the bare variant specifying a private key?
That should be the most practical use case, i.e. allowing unblinding
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, though I'd need to implement that :P. Give me a day or two. I think I can do it before ElementsProject/rust-elements#166 (which is blocking the reference implementation) gets in.
3d4d49b to
530cbf4
Compare
|
Sorry for the long delay. Switching to xpubs was easy but the view key support was pretty annoying because our elements-miniscript implementation doesn't directly relate secret key types to public key types, making it difficult to elegantly have "one key private, others public" for view keys. In the end I hacked it in, but as implemented it does not support e.g. ranged blinding keys. I have updated the test vectors in the ELIP, and the reference implementation at ElementsProject/elements-miniscript#31 |
|
|
||
| Using the <code>ct(slip77(<64-byte hex>), <DESCRIPTOR>)</code> construction, any wallet should be able to express its existing confidential addresses using this new scheme. | ||
|
|
||
| ==Test Vectors== |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add test vectors with non-extended public and private blinding keys?
elip-ct-descriptors.mediawiki
Outdated
| The following CT descriptors should be parseable and generate the given addresses: | ||
|
|
||
| * Valid Descriptor 1: <code>ct(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,elpkh(xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH))#y0lg3d5y</code> | ||
| ** Blinding public key: <code>xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL</code> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: the name here is slightly confusing, "blinding public key" is the one encoded in the confidential address, this is more like the "SLIP77 master blinding key", perhaps we should name it "master blinding public key" or "descriptor blinding public key". But any name is fine for me, as long we have different one wrt the derived (public) blinding keys
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, good point. I think I'll change this to "Descriptor blinding [public] key". Agreed it's confusing now that the key in the descriptor is different from the key in the address.
sanket1729
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 530cbf4. Sorry for my confusion on the PR review.
| * <code>slip77(<64-character hex>)</code> which indicates that blinding keys for these addresses are derived via SLIP77; or | ||
| * <code><KEY></code> which is an ordinary (extended) public key; the blinding key is derived by a Taproot-style tweak of the key with the data of <code><DESCRIPTOR></code>. | ||
|
|
||
| In the <code><KEY></code> expression, all key(s) must be compressed; x-only and uncompressed keys are invalid. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: It would be great if this specifically mentions KEY expression in descriptor spec. Reading the words compressed key confused me a bit.
another nit: This also mentions multi-path KEY expressions. I don't think we want to support that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does it mention multi-path KEY expressions? I did not even know those existed when I was writing this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps the "all key(s)" is confusing. There's just a single key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be a musig of multiple keys.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in the <KEY> expression?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Key expressions are defined as follows. https://github.com/bitcoin/bips/blob/master/bip-0380.mediawiki#key-expressions. I think what we mean to say that all KEY expressions that are not uncompressed keys are allowed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure. We say <code><KEY></code> which is an ordinary (extended) public key. We don't state anywhere that this is a "key expression" as in BIP380.
If it's supposed to be a key expression as in BIP380, we should say this. If not, we should consider renaming KEY.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I will reword this. Yes, it is supposed to be a key expression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though it would be nice if we had our own ELIP for key expressions so that we can extend it to support musig() eventually. Though I have zero interest in doing that. This ELIP has been more than enough standards work for one lifetime.
|
I apologize for not doing the test vectors yet. I will try to get them before the end of this week. Meanwhile we should really give this a number. I propose 150. If nobody complains I will assign this and update the PR tomorrow. |
|
|
||
| ===Overview=== | ||
| We propose a new <code>ct</code> descriptor which wraps any other descriptor type in the form <code>ct(<BLINDING_KEY>, <DESCRIPTOR>)</code>. | ||
| Here <code>DESCRIPTOR</code> refers to any existing descriptor, e.g. <code>elwsh(...)</code> or <code>eltr(...)</code> and <code>BLINDING_KEY</code> is a new expression which must be one of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Here <code>DESCRIPTOR</code> refers to any existing descriptor, e.g. <code>elwsh(...)</code> or <code>eltr(...)</code> and <code>BLINDING_KEY</code> is a new expression which must be one of | |
| Here <code>DESCRIPTOR</code> refers to any existing descriptor, e.g. <code>elwsh(...)</code> or <code>eltr(...)</code> |
Is this recursive - can a ct descriptor include another ct descriptor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, might be worth specifying (edit: sorry didn't realize you already had a reference implementation)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can I be more specific than "any existing descriptor"?
|
Updated exposition, added new test vectors, and assigned ELIP 150. |
sanket1729
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 5726891 . One small missing thing is that test vectors don't mention the address was created for elements regtest network.
pub const ELEMENTS: AddressParams = AddressParams {
p2pkh_prefix: 235,
p2sh_prefix: 75,
blinded_prefix: 4,
bech_hrp: "ert",
blech_hrp: "el",
};|
Thanks! Going to merge this. The test network thing is somewhat implicit by the prefix of the addresses, but we should mention it nonetheless. Can do this in a followup PR. |
This ELIP describes CT descriptors, as needed to attach blinding keys to existing descriptors and therefore create confidential addresses.
It does not cover:
Dupliicate of #1 created because of Github bugs.