@bitcoinerlab/descriptors 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,84 @@
1
+ A JavaScript library for parsing and signing Bitcoin descriptors, including those based on the Miniscript language.
2
+
3
+ Key features:
4
+ It allows signing using Hierarchical Deterministic keeps (those that use word mnemonics) and also Hardware Wallets (the Ledger wallet so far; more are comming).
5
+ It integrates miniscript, making it super easy to program advanced transactions. For example, timelock-based vaults, multisigs vaults or inheritance are now a breeze.
6
+ Dessigned to be used with psbt (Partially Signed Bitcion transactions) so that it can be used in mkuti-party scenarios.
7
+ Can be used with Typescript and Javascript.
8
+ Integrates with the bitcoinjs-lib family of modules.
9
+
10
+ Usage:
11
+
12
+ Installation:
13
+ npm install @bitcoinerlab/descriptors
14
+
15
+ Usage:
16
+
17
+ This section describes how to use this library, starting from a very easy transaction and ends up using a smart contract that only allows spending a transaction after a certain time, providing a certain secret (a preimage) and can only be unlocked by co-signing with a Ledger wallet and a Software Wallet.
18
+
19
+ We will show examples that have been run on the testnet network. We share the mnemonic we used so that you can replicate the transactions: . You won't be able to spend the transactions again but you will be able to replicate everything.
20
+
21
+ ```
22
+ MNEMONIC: "drum turtle globe inherit autumn flavor slice illness sniff distance carbon elder"
23
+ ```
24
+
25
+ TIP: you can use https://iancoleman.io/bip39/ to verify some of the steps below.
26
+
27
+ Simple case using standard transactions:
28
+
29
+ Let's start with an easy case. Let's send some sats from a Bitcoin Legacy address to a Segwit one.
30
+
31
+ We are ready to use the library. Here we skip all initialization. You will be able to see the complete code on a shared repository with the tests.
32
+
33
+ Examples are written using Javascript. If you want to use Typescript (recommended), please take a look to the test/integration folder for some advanced use use cases.
34
+ Please, note that the code below is just for explanation purposes. When writting code for production you must assert all intermediate steps.
35
+
36
+ ```javascript
37
+ //NETWORK is set to testnet
38
+ const masterNode = BIP32.fromSeed(mnemonicToSeedSync(MNEMONIC), NETWORK);
39
+ const descriptorLegacy = pkhBIP32({ masterNode, network: NETWORK, account: 0, change: 0, index: 1 });
40
+
41
+ console.log(descriptorLegacy.getAddress()); //moovc1JqGrz4v6FA2U8ks8ZqjSwjv3yRKQ
42
+ ```
43
+
44
+ So we sent some sats (`1679037`) to that address above. Those sats were sent in `TX_ID = "ee02b5a12c2f22e892bed376781fc9ed435f0d192a1b67ca47a7190804d8e868"`. [See it here](https://blockstream.info/testnet/tx/ee02b5a12c2f22e892bed376781fc9ed435f0d192a1b67ca47a7190804d8e868).
45
+
46
+ Now let's spend them. We will send all the funds, except for a fee to our first internal address (change 1) in account 0 of the P2WPKH (Segwit) wallet:
47
+
48
+ <!--https://coinfaucet.eu/en/btc-testnet/-->
49
+
50
+ ```javascript
51
+ const TX_ID = "ee02b5a12c2f22e892bed376781fc9ed435f0d192a1b67ca47a7190804d8e868";
52
+ const FEE = 100;
53
+
54
+ //Define the Segwit descriptor where we will receive the sats:
55
+ const descriptorSegwit = wpkhBIP32({ masterNode, network: NETWORK, account: 0, change: 1, index: 0 });
56
+
57
+ //Get some info from the network about the Legacy utxo we will spend from:
58
+ const txHex = await (await fetch(`https://blockstream.info/testnet/api/tx/${TX_ID}/hex`)).text();
59
+ const txOuts = (await (await fetch(`https://blockstream.info/testnet/api/tx/${TX_ID}`)).json()).vout;
60
+ const vout = txOuts.findIndex(txOut => txOut.scriptpubkey === descriptorLegacy.getScriptPubKey());
61
+ const initialValue = txOut[vout].value; //1679037, as mentioned above
62
+
63
+ //Create a transaction (Partially Signed Bitcoin Transaction) now:
64
+ const psbt = new Psbt({network: NETWORK});
65
+ //Update the transaction with the Legacy descriptor input:
66
+ const legacyInputNumber = descriptorLegacy.updatePsbt({ psbt, vout, txHex });
67
+ //Now add the Segwit address as the new output. Let's give some FEE to the miners
68
+ psbt.addOutput({ address: descriptorSegwit.getAddress(), value: initialValue - FEE});
69
+
70
+ //Sign the transaction, finalize it and submit it to the miners:
71
+ signBIP32({ psbt, masterNode });
72
+ descriptorLegacy.finalizePsbtInput({psbt, index: legacyInputNumber});
73
+ const spendTx = psbt.extractTransaction();
74
+ console.log(spendTx.getId()); //
75
+ await fetch('https://blockstream.info/testnet/api/tx', {
76
+ method: 'POST',
77
+ body: spendTx.toHex()
78
+ });
79
+ ```
80
+ We have sent the 1679037 - 100 to ourselves in just a few lines.
81
+ Easy! See the tx here: ....
82
+ This has only started. Let's do really cool stuff now.
83
+
84
+
package/README.md ADDED
@@ -0,0 +1,74 @@
1
+ ## Bitcoin Descriptors Library *Pre Release*
2
+
3
+ This library is designed to parse and create Bitcoin Descriptors, including Miniscript, and generate Partially Signed Bitcoin Transactions (PSBTs). It also provides PSBT finalizers and signers for single-signature, BIP32, and Hardware Wallets.
4
+
5
+ **NOTE: This is a pre-release version only.** The Usage documentation is still being finalized. However, you can take a look at the [integration tests](https://github.com/bitcoinerlab/descriptors/tree/main/test/integration) for some examples of how to use this library.
6
+
7
+ ### Features
8
+
9
+ - Parses and creates Bitcoin Descriptors (including those based on the Miniscript language).
10
+ - Generates Partially Signed Bitcoin Transactions (PSBTs).
11
+ - Provides PSBT finalizers and signers for single-signature, BIP32, and Hardware Wallets (currently supports Ledger devices; more devices are planned).
12
+
13
+ ### Usage
14
+
15
+ Usage instructions will be added to this README as soon as they are finalized. In the meantime, please refer to the [integration tests](https://github.com/bitcoinerlab/descriptors/tree/main/test/integration) for some examples of how to use this library.
16
+
17
+ ## Authors and Contributors
18
+
19
+ 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.
20
+
21
+ Here are some resources to help you get started with contributing:
22
+
23
+ ### Building from source
24
+
25
+ To download the source code and build the project, follow these steps:
26
+
27
+ 1. Clone the repository:
28
+
29
+ ```
30
+ git clone https://github.com/bitcoinerlab/descriptors.git
31
+ ```
32
+
33
+ 2. Install the dependencies:
34
+
35
+ ```
36
+ npm install
37
+ ```
38
+
39
+ 3. Build the project:
40
+
41
+ ```
42
+ npm run build
43
+ ```
44
+
45
+ This will build the project and generate the necessary files in the `dist` directory.
46
+
47
+ ### Testing
48
+
49
+
50
+ Before committing any code, make sure it passes all tests. First, make sure that you have a Bitcoin regtest node running and that you have set up the Express-based bitcoind manager from this repository: https://github.com/bitcoinjs/regtest-server. The manager should be running on 127.0.0.1:8080.
51
+
52
+ The easiest way to set up these services is to use a Docker image that comes preconfigured with them. You can use the following commands to download and run the Docker image:
53
+
54
+ ```bash
55
+ docker pull junderw/bitcoinjs-regtest-server
56
+ docker run -d -p 127.0.0.1:8080:8080 junderw/bitcoinjs-regtest-server
57
+ ```
58
+
59
+ This will start a container running a Bitcoin regtest node and the bitcoind manager on your machine. Once you have your node and manager set up, you can run the tests using the following command:
60
+
61
+ ```
62
+ npm run test
63
+ ```
64
+
65
+ And, in case you have a Ledger device:
66
+
67
+ ```
68
+ npm run test:integration:ledger
69
+ ```
70
+
71
+ ### License
72
+
73
+ This project is licensed under the MIT License.
74
+
@@ -0,0 +1,2 @@
1
+ export declare const CHECKSUM_CHARSET: string;
2
+ export declare const DescriptorChecksum: (span: string) => string;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DescriptorChecksum = exports.CHECKSUM_CHARSET = void 0;
4
+ // Converted to Javascript by Jose-Luis Landabaso, 2023 - https://bitcoinerlab.com
5
+ // Source: https://github.com/bitcoin/bitcoin/blob/master/src/script/descriptor.cpp
6
+ // Distributed under the MIT software license
7
+ const PolyMod = (c, val) => {
8
+ const c0 = c >> 35n;
9
+ c = ((c & 0x7ffffffffn) << 5n) ^ val;
10
+ if (c0 & 1n)
11
+ c ^= 0xf5dee51989n;
12
+ if (c0 & 2n)
13
+ c ^= 0xa9fdca3312n;
14
+ if (c0 & 4n)
15
+ c ^= 0x1bab10e32dn;
16
+ if (c0 & 8n)
17
+ c ^= 0x3706b1677an;
18
+ if (c0 & 16n)
19
+ c ^= 0x644d626ffdn;
20
+ return c;
21
+ };
22
+ exports.CHECKSUM_CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
23
+ const DescriptorChecksum = (span) => {
24
+ const INPUT_CHARSET = '0123456789()[],\'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#"\\ ';
25
+ let c = 1n;
26
+ let cls = 0n;
27
+ let clscount = 0n;
28
+ for (const ch of span) {
29
+ const pos = BigInt(INPUT_CHARSET.indexOf(ch));
30
+ if (pos === -1n)
31
+ return '';
32
+ c = PolyMod(c, pos & 31n);
33
+ cls = cls * 3n + (pos >> 5n);
34
+ if (++clscount === 3n) {
35
+ c = PolyMod(c, cls);
36
+ cls = 0n;
37
+ clscount = 0n;
38
+ }
39
+ }
40
+ if (clscount > 0n)
41
+ c = PolyMod(c, cls);
42
+ for (let j = 0; j < 8; ++j)
43
+ c = PolyMod(c, 0n);
44
+ c ^= 1n;
45
+ let ret = '';
46
+ for (let j = 0; j < 8; ++j) {
47
+ const index = (c >> (5n * (7n - BigInt(j)))) & 31n;
48
+ if (index < 0 || index > Number.MAX_SAFE_INTEGER)
49
+ throw new Error(`Error: could not compute checksum, invalid index ${index}`);
50
+ ret += exports.CHECKSUM_CHARSET[Number(index)];
51
+ }
52
+ return ret;
53
+ };
54
+ exports.DescriptorChecksum = DescriptorChecksum;
@@ -0,0 +1,15 @@
1
+ import { BIP32API } from 'bip32';
2
+ import { ECPairAPI } from 'ecpair';
3
+ import type { TinySecp256k1Interface, ParseKeyExpression, DescriptorInterfaceConstructor } from './types';
4
+ /**
5
+ * Builds the functions needed to operate with descriptors using an external elliptic curve (ecc) library.
6
+ * @param {Object} ecc - an object containing elliptic curve operations, such as [tiny-secp256k1](https://github.com/bitcoinjs/tiny-secp256k1) or [@bitcoinerlab/secp256k1](https://github.com/bitcoinerlab/secp256k1).
7
+ * @returns {Object} an object containing functions, `parse` and `checksum`.
8
+ * @namespace
9
+ */
10
+ export declare function DescriptorsFactory(ecc: TinySecp256k1Interface): {
11
+ Descriptor: DescriptorInterfaceConstructor;
12
+ ECPair: ECPairAPI;
13
+ parseKeyExpression: ParseKeyExpression;
14
+ BIP32: BIP32API;
15
+ };