@caravan/psbt 1.2.0 → 1.3.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.
- package/README.md +77 -54
- package/dist/index.d.ts +104 -1
- package/dist/index.js +92776 -42
- package/dist/index.mjs +92798 -64
- package/package.json +28 -7
- package/.eslintrc.cjs +0 -6
- package/.prettierrc +0 -4
- package/.turbo/turbo-build.log +0 -19
- package/.turbo/turbo-lint.log +0 -61
- package/.turbo/turbo-test.log +0 -99
- package/CHANGELOG.md +0 -28
- package/dist/index.d.mts +0 -324
- package/jest.config.js +0 -4
- package/src/index.ts +0 -2
- package/src/psbt.test.ts +0 -338
- package/src/psbt.ts +0 -440
- package/src/psbtv2/functions.ts +0 -169
- package/src/psbtv2/index.ts +0 -3
- package/src/psbtv2/psbtv2.test.ts +0 -1587
- package/src/psbtv2/psbtv2.ts +0 -1307
- package/src/psbtv2/psbtv2maps.ts +0 -111
- package/src/psbtv2/types.ts +0 -91
- package/src/psbtv2/values.ts +0 -4
- package/tsconfig.json +0 -3
- package/tsup.config.ts +0 -6
package/README.md
CHANGED
|
@@ -2,22 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
A set of utilities for working with PSBTs.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- [
|
|
8
|
-
- [Exports](#psbtv0-exports)
|
|
5
|
+
# Table of contents
|
|
6
|
+
- [Constants](#constants)
|
|
7
|
+
- [Exports](#exports)
|
|
9
8
|
- [`const PSBT_MAGIC_HEX`](#const-psbt_magic_hex)
|
|
10
9
|
- [`const PSBT_MAGIC_B64`](#const-psbt_magic_b64)
|
|
11
10
|
- [`const PSBT_MAGIC_BYTES`](#const-psbt_magic_bytes)
|
|
12
|
-
|
|
13
|
-
- [`function psbtInputFormatter`](#function-psbtinputformatter)
|
|
14
|
-
- [`function psbtOutputFormatter`](#function-psbtoutputformatter)
|
|
15
|
-
- [`function translatePSBT`](#function-translatepsbt)
|
|
16
|
-
- [`function addSignaturesToPSBT`](#function-addsignaturestopsbt)
|
|
17
|
-
- [`function parseSignaturesFromPSBT`](#function-parsesignaturesfrompsbt)
|
|
18
|
-
- [`function parseSignatureArrayFromPSBT`](#function-parsesignaturearrayfrompsbt)
|
|
11
|
+
- [PSBTv0](#psbtv0)
|
|
19
12
|
- [PSBTv2](#psbtv2)
|
|
20
|
-
- [Exports](#
|
|
13
|
+
- [Exports](#exports-1)
|
|
21
14
|
- [`class PsbtV2`](#class-psbtv2)
|
|
22
15
|
- [`get isReadyForConstructor`](#get-isreadyforconstructor)
|
|
23
16
|
- [`get isReadyForUpdater`](#get-isreadyforupdater)
|
|
@@ -40,11 +33,13 @@ A set of utilities for working with PSBTs.
|
|
|
40
33
|
- [Concepts](#concepts)
|
|
41
34
|
- [The operator role saga](#the-operator-role-saga)
|
|
42
35
|
- [TODO](#todo)
|
|
36
|
+
- [PsbtV2](#psbtv2-1)
|
|
37
|
+
- [Operator role validation](#operator-role-validation)
|
|
38
|
+
- [Class constructor](#class-constructor)
|
|
39
|
+
- [Add input timelocks](#add-input-timelocks)
|
|
40
|
+
- [Add input sighash\_single](#add-input-sighash_single)
|
|
43
41
|
|
|
44
|
-
##
|
|
45
|
-
|
|
46
|
-
[BIP 174](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki)
|
|
47
|
-
|
|
42
|
+
## Constants
|
|
48
43
|
### Exports
|
|
49
44
|
|
|
50
45
|
#### `const PSBT_MAGIC_HEX`
|
|
@@ -59,43 +54,13 @@ A utility constant for base64 encoded psbt magic bytes equal to `"cHNidP8"`.
|
|
|
59
54
|
|
|
60
55
|
A utility constant for `Buffer` instance of psbt magic bytes.
|
|
61
56
|
|
|
62
|
-
#### `function autoLoadPSBT`
|
|
63
|
-
|
|
64
|
-
Given a string, try to create a Psbt object based on MAGIC (hex or Base64).
|
|
65
|
-
|
|
66
|
-
#### `function psbtInputFormatter`
|
|
67
|
-
|
|
68
|
-
Take a `MultisigTransactionInput` and turn it into a `MultisigTransactionPSBTInput`.
|
|
69
|
-
|
|
70
|
-
#### `function psbtOutputFormatter`
|
|
71
57
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
#### `function translatePSBT`
|
|
75
|
-
|
|
76
|
-
Translates a PSBT into inputs/outputs consumable by supported non-PSBT devices in the `@caravan/wallets` library.
|
|
77
|
-
|
|
78
|
-
#### `function addSignaturesToPSBT`
|
|
79
|
-
|
|
80
|
-
Given an unsigned PSBT, an array of signing public key(s) (one per input), an array of signature(s) (one per input) in the same order as the pubkey(s), adds partial signature object(s) to each input and returns the PSBT with partial signature(s) included.
|
|
81
|
-
|
|
82
|
-
#### `function parseSignaturesFromPSBT`
|
|
83
|
-
|
|
84
|
-
Extracts the signature(s) from a PSBT.
|
|
85
|
-
|
|
86
|
-
NOTE: there should be one signature per input, per signer.
|
|
87
|
-
|
|
88
|
-
ADDITIONAL NOTE: because of the restrictions we place on braids to march their multisig addresses (slices) forward at the _same_ index across each chain of the braid, we do not run into a possible collision with this data structure. BUT - to have this method accommodate the _most_ general form of signature parsing, it would be wise to wrap this one level deeper like:
|
|
58
|
+
## PSBTv0
|
|
89
59
|
|
|
90
|
-
|
|
91
|
-
address: [pubkey : [signature(s)]]
|
|
92
|
-
```
|
|
60
|
+
[BIP 174](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki)
|
|
93
61
|
|
|
94
|
-
that way if your braid only advanced one chain's (member's) index so that a pubkey could be used in more than one address, everything would still function properly.
|
|
95
62
|
|
|
96
|
-
#### `function parseSignatureArrayFromPSBT`
|
|
97
63
|
|
|
98
|
-
Extracts signatures in order of inputs and returns as array (or array of arrays if multiple signature sets).
|
|
99
64
|
|
|
100
65
|
## PSBTv2
|
|
101
66
|
|
|
@@ -246,22 +211,80 @@ Attempts to extract the version number as uint32LE from raw psbt regardless of p
|
|
|
246
211
|
|
|
247
212
|
The PSBT is a resource which may be passed between several operators or services. It's best to look at the operator roles as stages of a saga. The next valid operator role(s) can be determined by the state of the PSBT. The actions allowed for a PSBT are determined by which operator role the PSBT can be now and which role it could be next. See the following blog article at Unchained for a more detailed illustration: [Operator roles: Life stages in the saga of a PSBT](https://unchained.com/blog/operator-roles-life-stages-in-the-saga-of-a-psbt/)
|
|
248
213
|
|
|
249
|
-
|
|
214
|
+
## TODO
|
|
250
215
|
|
|
251
|
-
|
|
216
|
+
### PsbtV2
|
|
252
217
|
|
|
253
|
-
|
|
218
|
+
#### Operator role validation
|
|
254
219
|
|
|
255
220
|
Work remains for determining readiness for operator roles Input Finalizer and Transaction Extractor. The getters responsible for these checks are `isReadyForInputFinalizer` and `isReadyForTransactionExtractor`. Work also remains to expand the PsbtV2 method functionality beyond the Signer role. A huge benefit might be gained from building methods aimed at the Combiner role.
|
|
256
221
|
|
|
257
|
-
|
|
222
|
+
#### Class constructor
|
|
258
223
|
|
|
259
224
|
The constructor must be able to handle values which the Creator role is responsible for. Currently, the constructor can only accept an optional psbt which it parses to configure itself. It would be ideal if a fresh PsbtV2 instance could be initialized with minimal arguments for which the Creator role is responsible. See `private create()`.
|
|
260
225
|
|
|
261
|
-
|
|
226
|
+
#### Add input timelocks
|
|
262
227
|
|
|
263
228
|
The `public addInput` must be able to properly handle input locktimes which interact with the global value.
|
|
264
229
|
|
|
265
|
-
|
|
230
|
+
#### Add input sighash_single
|
|
266
231
|
|
|
267
232
|
The `public addInput` must be able to properly handle new inputs when the psbt has a `SIGHASH_SINGLE` flag on `PSBT_GLOBAL_TX_MODIFIABLE`.
|
|
233
|
+
|
|
234
|
+
## Troubleshooting and FAQ
|
|
235
|
+
### What's with the vendor version of tiny-secp256k1?
|
|
236
|
+
In v6 of bitcoinjs-lib, which @caravan/psbt upgraded to use relative v5 in the older psbt code in @caravan/bitcoin,
|
|
237
|
+
some functions of the library require an elliptic curve library to be initialized w/ bitcoinjs-lib (see [this issue](https://github.com/bitcoinjs/bitcoinjs-lib/issues/1889#issuecomment-1443792692)), e.g. for taproot functionality.
|
|
238
|
+
For some reason, the recommended library `tiny-secp256k1` fails on initialization saying the library is invalid. The cause
|
|
239
|
+
seems to be a comparison of a Buffer with Uint8Array (see [this issue](https://github.com/bitcoinjs/tiny-secp256k1/issues/136) for more info).
|
|
240
|
+
|
|
241
|
+
A proposed fix is pending review and approval [here](https://github.com/bitcoinjs/tiny-secp256k1/pull/137). Unfortunately, since there
|
|
242
|
+
is a special build requirement to get the package code, the easiest way to get bitcoinjs initialized was to include patched vendor code in
|
|
243
|
+
the caravan codebase for now.
|
|
244
|
+
|
|
245
|
+
If a fork needs to be maintained and updated, to build and update the code, you can fork the repo, and run the docker build steps:
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
% docker build -t tiny-secp256k1 .
|
|
249
|
+
% docker run -it --rm -v `pwd`:/tiny-secp256k1 -w /tiny-secp256k1 tiny-secp256k1
|
|
250
|
+
# make build
|
|
251
|
+
```
|
|
252
|
+
Then copy the resulting built code (ends up in the lib directory) into the vendor/tiny-secp256k1. Currently
|
|
253
|
+
we just use the asmjs build to avoid wasm complications in
|
|
254
|
+
the build system.
|
|
255
|
+
|
|
256
|
+
### Experimental VM Modules
|
|
257
|
+
This is related to the tiny-secp256k1 library which has difficulties importing in different environments.
|
|
258
|
+
|
|
259
|
+
Note that the jest configs and the special prefix in the npm test scripts were needed
|
|
260
|
+
to let jest understand the esmodule imports from the tiny-secp256k1 library.
|
|
261
|
+
|
|
262
|
+
The npm script prefix in particular may result in a console warning when running tests:
|
|
263
|
+
|
|
264
|
+
```
|
|
265
|
+
ExperimentalWarning: VM Modules is an experimental feature and might change at any time
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
This can be safely ignored. See the [documentation in jest](https://jestjs.io/docs/ecmascript-modules)
|
|
269
|
+
for more information on running with `--experimental-vm-modules`.
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
### What's with the `bitcoinjs-lib-v6` dependency?
|
|
273
|
+
|
|
274
|
+
npm workspaces and maybe vite have issues with nested dependencies with
|
|
275
|
+
mismatched versions. `@caravan/psbt` requires v6 of bitcoinjs-lib but in order
|
|
276
|
+
to avoid making massive breaking changes, other libraries like `@caravan/bitcoin` are
|
|
277
|
+
still using bitcoinjs-lib v5. Unfortunately when being built altogether, it's possible
|
|
278
|
+
that the wrong version takes precedence, causing the build to break.
|
|
279
|
+
|
|
280
|
+
Because npm lacks a `nohoist` option for workspaces, the workaround is to use a kind
|
|
281
|
+
of alias in the package.json. So we add `"bitcoinjs-lib-v6": "npm:bitcoinjs-lib@^6.1.5",`
|
|
282
|
+
to say that we want to use v6.1.5 from npm whenever use the alias `bitcoinjs-lib-v6`
|
|
283
|
+
in imports in our code. This forces build systems to look for this reference and
|
|
284
|
+
the correct version of the package and avoid using a mismatch. Unfortunately
|
|
285
|
+
this was the only workaround that worked. `overrides` for example was not being
|
|
286
|
+
respected.
|
|
287
|
+
|
|
288
|
+
Learn more [here](https://github.com/vitejs/vite/issues/4245),
|
|
289
|
+
[here](https://github.com/zackerydev/noist?tab=readme-ov-file), and
|
|
290
|
+
[here](https://github.com/prisma/prisma/issues/9649).
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { Network } from '@caravan/bitcoin';
|
|
2
|
+
import { Psbt } from 'bitcoinjs-lib-v6';
|
|
3
|
+
import { MultisigWalletConfig } from '@caravan/multisig';
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
6
|
* Hex encoded string containing `<keytype><keydata>`. A string is needed for
|
|
3
7
|
* Map.get() since it matches by identity. Most commonly, a `Key` only contains a
|
|
@@ -321,4 +325,103 @@ declare class PsbtV2 extends PsbtV2Maps {
|
|
|
321
325
|
static FromV0(psbt: string | Buffer, allowTxnVersion1?: boolean): PsbtV2;
|
|
322
326
|
}
|
|
323
327
|
|
|
324
|
-
|
|
328
|
+
interface PsbtInput {
|
|
329
|
+
hash: string | Buffer;
|
|
330
|
+
index: number;
|
|
331
|
+
transactionHex: string;
|
|
332
|
+
redeemScript?: Buffer;
|
|
333
|
+
witnessScript?: Buffer;
|
|
334
|
+
bip32Derivation?: {
|
|
335
|
+
masterFingerprint: Buffer;
|
|
336
|
+
path: string;
|
|
337
|
+
pubkey: Buffer;
|
|
338
|
+
}[];
|
|
339
|
+
spendingWallet: MultisigWalletConfig;
|
|
340
|
+
}
|
|
341
|
+
interface PsbtOutput {
|
|
342
|
+
address: string;
|
|
343
|
+
value: number;
|
|
344
|
+
bip32Derivation?: {
|
|
345
|
+
masterFingerprint: Buffer;
|
|
346
|
+
path: string;
|
|
347
|
+
pubkey: Buffer;
|
|
348
|
+
}[];
|
|
349
|
+
redeemScript?: Buffer;
|
|
350
|
+
witnessScript?: Buffer;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* This function seeks to be an updated version of the legacy `unsignedMultisigPSBT` function
|
|
354
|
+
* from @caravan/bitcoin.
|
|
355
|
+
* It takes the network and a set of inputs and outputs which it creates a PSBT from.
|
|
356
|
+
* This combines several operator roles of the PSBT saga into one function, getting a PSBT
|
|
357
|
+
* ready to be signed. It optionally can also add the global xpubs to the PSBT.
|
|
358
|
+
*/
|
|
359
|
+
declare const getUnsignedMultisigPsbtV0: ({ network, inputs, outputs, includeGlobalXpubs, }: {
|
|
360
|
+
network: Network;
|
|
361
|
+
inputs: PsbtInput[];
|
|
362
|
+
outputs: PsbtOutput[];
|
|
363
|
+
includeGlobalXpubs?: boolean | undefined;
|
|
364
|
+
}) => Psbt;
|
|
365
|
+
declare const addGlobalXpubs: (psbt: Psbt, inputs: PsbtInput[], network: Network) => void;
|
|
366
|
+
/**
|
|
367
|
+
* Validate the signature on a psbt for a given input. Returns false if no
|
|
368
|
+
* valid signature is found otherwise returns the public key that was signed for.
|
|
369
|
+
*
|
|
370
|
+
* This is a port of the validateMultisigSignature function from @caravan/bitcoin
|
|
371
|
+
* to support a newer API and be more PSBT-native.
|
|
372
|
+
*/
|
|
373
|
+
declare const validateMultisigPsbtSignature: (raw: string | Buffer, inputIndex: number, inputSignature: Buffer, inputAmount?: string) => boolean | string;
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* @file This file primarily contains utility functions migrated from the
|
|
377
|
+
* legacy psbt module in @caravan/bitcoin. With the new @caravan/psbt
|
|
378
|
+
* module, the goal is to make a more modular and legible API. But in order
|
|
379
|
+
* to make migrations easier from the old API, we need to provide conversion functions
|
|
380
|
+
* for converting the deeply nested objects in the legacy API.
|
|
381
|
+
*/
|
|
382
|
+
|
|
383
|
+
interface LegacyMultisig {
|
|
384
|
+
/**
|
|
385
|
+
* JSON stringified object with the following properties:
|
|
386
|
+
* braidDetails: {
|
|
387
|
+
* network: Network;
|
|
388
|
+
* addressType: number;
|
|
389
|
+
* extendedPublicKeys: string[];
|
|
390
|
+
* requiredSigners: number;
|
|
391
|
+
* index: string;
|
|
392
|
+
* };
|
|
393
|
+
*/
|
|
394
|
+
braidDetails: string;
|
|
395
|
+
bip32Derivation?: {
|
|
396
|
+
masterFingerprint: string;
|
|
397
|
+
path: string;
|
|
398
|
+
pubkey: Buffer;
|
|
399
|
+
}[];
|
|
400
|
+
}
|
|
401
|
+
interface LegacyInput {
|
|
402
|
+
txid: string;
|
|
403
|
+
index: number;
|
|
404
|
+
transactionHex: string;
|
|
405
|
+
amountSats: number | string;
|
|
406
|
+
multisig: LegacyMultisig;
|
|
407
|
+
}
|
|
408
|
+
interface LegacyOutput {
|
|
409
|
+
address: string;
|
|
410
|
+
amountSats: number | string;
|
|
411
|
+
bip32Derivation?: {
|
|
412
|
+
masterFingerprint: string;
|
|
413
|
+
path: string;
|
|
414
|
+
pubkey: Buffer;
|
|
415
|
+
}[];
|
|
416
|
+
witnessScript?: Buffer;
|
|
417
|
+
redeemScript?: Buffer;
|
|
418
|
+
multisig?: LegacyMultisig;
|
|
419
|
+
}
|
|
420
|
+
declare const convertLegacyInput: (input: LegacyInput) => PsbtInput;
|
|
421
|
+
declare const convertLegacyOutput: (output: LegacyOutput) => PsbtOutput;
|
|
422
|
+
|
|
423
|
+
declare const PSBT_MAGIC_HEX = "70736274ff";
|
|
424
|
+
declare const PSBT_MAGIC_B64 = "cHNidP8";
|
|
425
|
+
declare const PSBT_MAGIC_BYTES: Buffer;
|
|
426
|
+
|
|
427
|
+
export { LegacyInput, LegacyMultisig, LegacyOutput, PSBT_MAGIC_B64, PSBT_MAGIC_BYTES, PSBT_MAGIC_HEX, PsbtInput, PsbtOutput, PsbtV2, addGlobalXpubs, convertLegacyInput, convertLegacyOutput, getPsbtVersionNumber, getUnsignedMultisigPsbtV0, validateMultisigPsbtSignature };
|