ELIP: 151 Layer: Wallet Title: Deterministic Descriptor Blinding Keys Author: Leonardo Comandini <[email protected]> Comments-Summary: No comments yet. Comments-URI: https://github.com/ElementsProject/elips/wiki/Comments:ELIP-???? Status: Draft Type: Standards Track Created: 2023-11-08 License: BSD-3-Clause
This document proposes a standard way to deterministically derive the descriptor blinding key in view descriptors.
This document is licensed under the 3-clause BSD license.
CT descriptors as defined in ELIP-150 consist of a descriptor blinding key and an ordinary descriptor.
Descriptor blinding keys can be chosen arbitrarily. This however increases the amount of data that the user needs to back up.
Otherwise they can be deterministically derived from a BIP32 seed following SLIP-77. This works for singlesig wallets, since the only backup that the user needs is the BIP32 seed (or BIP39 mnemonic). However this does not apply to multisig wallets which usually consist of multiple xpubs, and thus multiple BIP32 seeds from which a descriptor blinding key could be derived. SLIP77 also does not work well when there are multiple BIP44 accounts, as they will have the same master blinding key.
This document defines a standard way to deterministically derive a descriptor blinding key from an ordinary descriptor.
Deriving the descriptor blinding key from the ordinary descriptor means that multisig participants can avoid needing a key construction and sharing protocol.
We propose a new possible value for the descriptor blinding key
ct(elip151,<DESCRIPTOR>)
Which indicates that descriptor blinding key to be used is a view key deterministically derived from the ordinary descriptor DESCRIPTOR
If a wallet uses this standard to derive its descriptor blinding key, anyone knowing the ordinary descriptor will be able to unblind all the corresponding outputs.
Potential adopters of this standard should consider whether this behavior is acceptable.
The following descriptor:
ct(elip151,<DESCRIPTOR>)
Is equivalent to:
ct(<KEY>,<DESCRIPTOR>)
Where KEY
is a ELIP-150 view blinding key derived as follows:
- If the top-level script expression is
combo
, fail. - If the descriptor does not have wildcards, fail.
- Future extensions that support multiple descriptors other than multi-path are not supported.
- If
DESCRIPTOR
is multi-path, expand to every single descriptor following BIP-389 rules[1] - For each single descriptor:
- Get the definite descriptor at index 231-1[2]
- Derive the
scriptPubKey
from the definite descriptor[3] - Encode
OP_INVALIDOPCODE
following the consensus encoding, i.e. prefixed with its length. - Encode the
scriptPubKey
following the consensus encoding. - Concatenate these two values; for instance for scriptpubkey
0014aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
, the encoding is01ff160014aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
.
- Concatenate all values computed before, obtaining
scriptPubKeys
. - Let Htag be a BIP-340 tagged hash with tag
Deterministic-View-Key/1.0
[4] - The descriptor blinding key is the tagged hash of the concatenated prefixed
scriptPubKey
s,KEY
= Htag(scriptPubKeys
) mod n, converted to hex format.
The following ordinary descriptors yield to the given descriptor blinding keys:
- Test vector 1
- Ordinary descriptor:
elwpkh(xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/<0;1>/*)#lg37z46y
- Derived descriptor blinding key:
b3baf94d60cf8423cd257283575997a2c00664ced3e8de00f8726703142b1989
- Derived confidential descriptor:
ct(b3baf94d60cf8423cd257283575997a2c00664ced3e8de00f8726703142b1989,elwpkh(xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/<0;1>/*))#tu4ggqlv
- Derived confidential descriptor (equivalent version):
ct(elip151,elwpkh(xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/<0;1>/*))#m47kvl05
- First address:
lq1qqt33kuqusp3amjam96zxg27wvg2ewvl69h3equtck8lk8349vrxt28w2wqel8nstvtmefmexkn9zg5hhku2u7kr9k068fk338
- Ordinary descriptor:
- Test vector 2
- Ordinary descriptor:
elwpkh(xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/0/*)#xshkmp3l
- Derived descriptor blinding key:
de9c5fb624154624146a8aea0489b30f05c720eed6b493b1f3ab63405a11bf37
- Derived confidential descriptor:
ct(de9c5fb624154624146a8aea0489b30f05c720eed6b493b1f3ab63405a11bf37,elwpkh(xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/0/*))#34lpke0s
- Derived confidential descriptor (equivalent version):
ct(elip151,elwpkh(xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/0/*))#y0su9u33
- First address:
lq1qqwv7x220qlm8kwjewuwcdl2c88n202jx4ug7fhjdj3xt25my2zq0w8w2wqel8nstvtmefmexkn9zg5hhku2u7gc263jye380e
- Ordinary descriptor:
- Test vector 3
- Ordinary descriptor:
elwsh(multi(2,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/<0;1>/*,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/0/<0;1>/*))#fmdhs428
- Derived descriptor blinding key:
7fcc1b9a20bbf611d157016192a7d28e353033cfa6a4885b3c48fa5ff9ce1881
- Derived confidential descriptor:
ct(7fcc1b9a20bbf611d157016192a7d28e353033cfa6a4885b3c48fa5ff9ce1881,elwsh(multi(2,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/<0;1>/*,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/0/<0;1>/*)))#95nx0s57
- Derived confidential descriptor (equivalent version):
ct(elip151,elwsh(multi(2,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/<0;1>/*,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/0/<0;1>/*)))#r5qqsf3v
- First address:
lq1qqgf45fhn528h6ermjvlfu38mquw64y8n9pklwww7nzrv280rjd6uat46xe03nxat42fqavhf5edmmhy7yk0e4hvrs4eackgkyjw8su877ktyl57pnjfu
- Ordinary descriptor:
- Test vector 4
- Ordinary descriptor:
elwsh(multi(2,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/<0;1>/*,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/0/<1;2>/*))#cagw3lzd
- Derived descriptor blinding key:
ff0a08050417f0ca95fb6ef7df979ae464739cb79b8c8f4b05408e0ac681a527
- Derived confidential descriptor:
ct(ff0a08050417f0ca95fb6ef7df979ae464739cb79b8c8f4b05408e0ac681a527,elwsh(multi(2,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/<0;1>/*,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/0/<1;2>/*)))#5ym2hpzd
- Derived confidential descriptor (equivalent version):
ct(elip151,elwsh(multi(2,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/<0;1>/*,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/0/<1;2>/*)))#ft7v5az2
- First address:
lq1qq0ccdus59lma7pyqjc0gfcgnc9pwlwmlg23el8zame3evv0mslzes04l80049f6jdn4ml26n7c4aq5gqslfzx263zeww6nsrtu3udnm4nclecdvua9v5
- Ordinary descriptor:
The following descriptors are not supported:
- Invalid Test vector 1
- Ordinary descriptor:
elwpkh(xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8)#5putv8ts
- Invalid confidential descriptor:
ct(elip151,elwpkh(xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8))#hf047rv6
- Ordinary descriptor:
- Invalid Test vector 2
- Ordinary descriptor:
elwpkh(03d902f35f560e0470c63313c7369168d9d7df2d49bf295fd9fb7cb109ccee0494)#f9x8raer
- Invalid confidential descriptor:
ct(elip151,elwpkh(03d902f35f560e0470c63313c7369168d9d7df2d49bf295fd9fb7cb109ccee0494))#3fcvdxu3
- Ordinary descriptor:
- Invalid Test vector 3
- Ordinary descriptor:
elwsh(multi(2,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/<0;1>/*,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/0/<0;1;2>/*))#dvazw5jp
- Invalid confidential descriptor:
ct(elip151,elwsh(multi(2,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/<0;1>/*,xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8/0/<0;1;2>/*)))#gkrp8f5z
- Ordinary descriptor:
- ^ Multi-path with mismatching length are disallowed, multi-path are derived in parallel.
- ^
We want to use a
scriptPubKey
that will not be used in a transaction. Otherwise it can be used directly by anyone to derive the descriptor blinding key. Wallets usescriptPubKey
s starting from index 0, thus we choose the last non-hardened index, which in practice will never be used in a transaction. - ^
Here we use the
scriptPubKey
because descriptors have fields that might change without affecting the spending conditions. For instance changing the fingerprint of one xpub yields the samescriptPubKey
s. Using thescriptPubKey
allows us to treat such descriptors as equivalent. - ^ A tagged hash is used to make sure hashes used in this context can't be reinterpreted in another one.
We would like to thank Jon Griffiths for suggesting the idea of deriving descriptor blinding key from the ordinary descriptor.