Skip to content

Instantly share code, notes, and snippets.

@dr-orlovsky
Created February 22, 2023 09:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dr-orlovsky/2a2ed8de8ae5e819cc6581d8fd512619 to your computer and use it in GitHub Desktop.
Save dr-orlovsky/2a2ed8de8ae5e819cc6581d8fd512619 to your computer and use it in GitHub Desktop.
Descriptor script fragment

Descriptor script fragment

Miniscript is great, but:

  1. Can’t represent many wallet types inside descriptor (lightning wallet, multisigs re-using keys in different branches)
  2. Do not yet supports tapscript
  3. Still not stable, i.e. not durable enough for long storage of wallet descriptor backups

As of today, there is no standard way to write a descriptor covering all forms of UTXOs which may be present in bitcoin transactions. This standards aims to bridge that gap. It also defines a canonical form of a wallet descriptor, which is unique for each wallet and allows to commit to the wallet structure in a non-ambigous way, which may be important for wallet comparison, identification, especially in multi-party protocols.

Standard proposes new script() fragment for wallet descriptors. It takes the following variants of a single argument:

  1. Templated opcode form, in which script composed of opcodes and tempaltes separated with whitespaces
  2. Templated hex form, in which script consists of hexacecimal fragments and templates without whitespace

Templates are defined as <> pattern can has the following forms:

  1. Push representing OP_FALSE (i.e. empty string) <>
  2. Push of a pubkey derivable from a pubkey or privkey descriptor
  3. Push of a decimal integer in its little-endian representation, like <495>
  4. Push of a hexadecimal integer (binary string), which must be prefixed with 0x, like <0xff>
  5. Push of a ASCII string, kept in double quotation marks, like <“some string to push”>
  6. Push of a value or derived public key presented by a named variable, like <pk>. The variable name can be composed of alphanumeric, -, _ and . characters and can’t start with a digit. It should be prefixed with decimal prefix specifying the length of the variable, if it has a fixed length, like <33:pk>, which helps in static analysis of the script size.

Canonical form

  1. Script must be converted into templated hex form
  2. All public keys SHOULD be formatted as templates even if they are parts of non-template script
  3. All private keys must be converted into public key form

Satisfaction

Manually provided in parallel with the descriptor in a form defined by other standards, or, otherwise, analyzed by parsing script fragment content with miniscript and by utilizing its satisfaction analysis capabilities.

Examples

Lightning network

Descriptor for a lightning to_local outputs defined by BOLT-3:

wsh(script(
	<key_local> OP_CHECKSIG OP_NOTIF
	  <key_revocation> OP_CHECKSIG
	OP_ELSE
	  <0xF003> OP_CHECKSEQUENCEVERIFY
	OP_ENDIF
))

As it can be see, it literally works with the code provided in BOLT-3 with just a single modification to hexadecimal value representation.

Multisig with repeated keys

wsh(script(
  <3> <signer.1> <signer.2> <signer.3> <3> OP_CHECKMULTISIG
  OP_IFNOT 
    <0xE801> OP_CHECKTIMELOCKVERIFY
    <3> <signer.1> <signer.2> <signer.3> <2> OP_CHECKMULTISIG
  OP_ENDIF
))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment