From 78cade877da163ae24439003fc02d50ea4ba022a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Luis=20Landabaso=20D=C3=ADaz?= Date: Thu, 29 Dec 2022 10:31:03 +0100 Subject: [PATCH] Update README with Miniscript link and description, and improve satisfier documentation adding a link to the playground --- README.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++------ package.json | 4 ++-- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d482cf2..7363004 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Bitcoin Miniscript -This project is a JavaScript implementation of Bitcoin Miniscript, a high-level language for describing Bitcoin spending conditions. +This project is a JavaScript implementation of [Bitcoin Miniscript](https://bitcoin.sipa.be/miniscript/), a high-level language for describing Bitcoin spending conditions. -It includes a transpilation of [Peter Wuille's C++ code](https://github.com/sipa/miniscript) for compiling spending policies into Miniscript and Bitcoin scripts, as well as a novel Miniscript Satisfier for generating explicit witness scripts that are decoupled from the tx signer. +It includes a novel Miniscript Satisfier for generating explicit witness scripts that are decoupled from the tx signer, as well as a transpilation of [Peter Wuille's C++ code](https://github.com/sipa/miniscript) for compiling spending policies into Miniscript and Bitcoin scripts. ## Features @@ -11,11 +11,13 @@ It includes a transpilation of [Peter Wuille's C++ code](https://github.com/sipa - The Miniscript Satisfier is able to generate explicit witness scripts from Miniscripts using variables, such as `pk(key)`. For example, Miniscript `and_v(v:pk(key),after(10))` can be satisfied with `[{ witness: '', nLockTime: 10 }]`. + - The ability to generate different satisfactions depending on the presence of `unknowns`. For example, Miniscript `c:and_v(or_c(pk(key1),v:ripemd160(H)),pk_k(key2))` can be satisfied with: `[{ witness: ' 0' }]`. However, if `unknowns: ['']` is set, then the Miniscript can be satisfied with: `[{ witness: ' ' }]` because this solution can no longer be considered malleable, given then assumption that an attacker does not have access to the preimage. + - Thoroughly tested. ## Installation @@ -28,6 +30,8 @@ npm install @bitcoinerlab/miniscript ## Usage +You can test the examples in this section using the online playground demo available at https://bitcoinerlab.com/modules/miniscript. + ### Compiling Policies into Miniscript and Bitcoin script To compile a Policy into a Miniscript and Bitcoin ASM, you can use the `compilePolicy` function: @@ -39,6 +43,7 @@ const policy = 'or(and(pk(A),older(8640)),pk(B))'; const { miniscript, asm, issane } = compilePolicy(policy); ``` + `issane` is a boolean that indicates whether the Miniscript is valid and follows the consensus and standardness rules for Bitcoin scripts. A sane Miniscript should have non-malleable solutions, not mix different timelock units on a single branch of the script, and not contain duplicate keys. In other words, it should be a well-formed and standards-compliant script that can be safely used in transactions. ### Compiling Miniscript into Bitcoin script @@ -63,11 +68,27 @@ const { satisfier } = require('@bitcoinerlab/miniscript'); const miniscript = 'c:or_i(andor(c:pk_h(key1),pk_h(key2),pk_h(key3)),pk_k(key4))'; -const satisfactions = satisfier(miniscript); +const { nonMalleableSats, malleableSats } = satisfier(miniscript); ``` -`satisfier` makes sure that output `satisfactions` are non-malleable and that the `miniscript` is sane. -You can also set `unknowns`: +`satisfier` makes sure that output `satisfactions` are non-malleable and that the `miniscript` is sane by itself and it returns an object with keys: + +- `nonMalleableSats`: an array of objects representing good, non-malleable witnesses. +- `malleableSats`: an array of objects representing malleable witnesses that should not be used. + +In the example above `nonMalleableSats` is: + +```javascript +nonMalleableSats: [ + {witness: " 0"} + {witness: " 0 1"} + {witness: " 1"} +] +``` + +Where satisfactions are ordered in ascending Weight Unit size. + +In addition, `unknowns` can be set with the pieces of information the user does not have, f.ex., `` or ``: ```javascript const { satisfier } = require('@bitcoinerlab/miniscript'); @@ -76,9 +97,28 @@ const miniscript = 'c:or_i(andor(c:pk_h(key1),pk_h(key2),pk_h(key3)),pk_k(key4))'; const unknowns = ['', '']; -const satisfactions = satisfier(miniscript, unknowns); +const { nonMalleableSats, malleableSats, unknownSats } = satisfier( + miniscript, + unknowns +); +``` + +When passing `unknowns`, `satisfier` returns an addition object key: `{ unknownSats }`with an array of objects representing satisfactions that containt some of the `unknown` pieces of information: + +```javascript +nonMalleableSats: [ + {witness: " 0"} + {witness: " 0 1"} +] +unknownSats: [ {witness: " 1"} ] ``` +The objects returned in the `nonMalleableSats`, `malleableSats` and `unknownSats` arrays consist of the following properties: + +- `witness`: a string with the witness script. +- `nSequence`: an integer representing the nSequence value, if needed. +- `nLockTime`: an integer representing the nLockTime value, if needed. + ## Authors and Contributors The project was initially developed and is currently maintained by [Jose-Luis Landabaso](https://github.com/landabaso). Contributions and help from other developers are welcome. diff --git a/package.json b/package.json index 6779e4d..1dded92 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "asm", "descriptors" ], - "homepage": "https://bitcoinerlab.com/miniscript", - "version": "1.0.2", + "homepage": "https://bitcoinerlab.com/modules/miniscript", + "version": "1.0.3", "description": "Bitcoin Miniscript, a high-level language for describing Bitcoin spending conditions. It includes a Policy and Miniscript compiler, as well as a novel Satisfier for generating expressive witness scripts.", "main": "dist/index.js", "scripts": {