@bitcoinerlab/descriptors 2.1.0 → 2.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.
- package/README.md +2 -2
- package/dist/descriptors.d.ts +22 -2
- package/dist/descriptors.js +22 -9
- package/dist/psbt.d.ts +2 -1
- package/dist/psbt.js +14 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -84,10 +84,10 @@ To call `updatePsbtAsInput()`, use the following syntax:
|
|
|
84
84
|
```javascript
|
|
85
85
|
import { Psbt } from 'bitcoinjs-lib';
|
|
86
86
|
const psbt = new Psbt();
|
|
87
|
-
const inputFinalizer = output.updatePsbtAsInput({ psbt, txHex, vout });
|
|
87
|
+
const inputFinalizer = output.updatePsbtAsInput({ psbt, txHex, vout, rbf });
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
Here, `psbt` refers to an instance of the [bitcoinjs-lib Psbt class](https://github.com/bitcoinjs/bitcoinjs-lib). The parameter `txHex` denotes a hex string that serializes the previous transaction containing this output. Meanwhile, `vout` is an integer that marks the position of the output within that transaction.
|
|
90
|
+
Here, `psbt` refers to an instance of the [bitcoinjs-lib Psbt class](https://github.com/bitcoinjs/bitcoinjs-lib). The parameter `txHex` denotes a hex string that serializes the previous transaction containing this output. Meanwhile, `vout` is an integer that marks the position of the output within that transaction. Finally, `rbf` is an optional parameter (defaulting to `true`) used to indicate whether the transaction uses Replace-By-Fee (RBF). When RBF is enabled, transactions can be replaced while they are in the mempool with others that have higher fees. Note that RBF is enabled for the entire transaction if at least one input signals it. Also, note that transactions using relative time locks inherently opt into RBF due to the `nSequence` range used.
|
|
91
91
|
|
|
92
92
|
The method returns the `inputFinalizer()` function. This finalizer function completes a PSBT input by adding the unlocking script (`scriptWitness` or `scriptSig`) that satisfies the previous output's spending conditions. Bear in mind that both `scriptSig` and `scriptWitness` incorporate signatures. As such, you should complete all necessary signing operations before calling `inputFinalizer()`. Detailed [explanations on the `inputFinalizer` method](#signers-and-finalizers-finalize-psbt-input) can be found in the Signers and Finalizers section.
|
|
93
93
|
|
package/dist/descriptors.d.ts
CHANGED
|
@@ -158,6 +158,7 @@ export declare function DescriptorsFactory(ecc: TinySecp256k1Interface): {
|
|
|
158
158
|
txId?: string;
|
|
159
159
|
value?: number;
|
|
160
160
|
vout: number;
|
|
161
|
+
rbf?: boolean;
|
|
161
162
|
}): number;
|
|
162
163
|
/**
|
|
163
164
|
* Sets this output as an input of the provided `psbt` and updates the
|
|
@@ -176,6 +177,14 @@ export declare function DescriptorsFactory(ecc: TinySecp256k1Interface): {
|
|
|
176
177
|
*
|
|
177
178
|
* When unsure, always use `txHex`, and skip `txId` and `value` for safety.
|
|
178
179
|
*
|
|
180
|
+
* Use `rbf` to mark whether this tx can be replaced with another with
|
|
181
|
+
* higher fee while being in the mempool. Note that a tx will automatically
|
|
182
|
+
* be marked as replacable if a single input requests it.
|
|
183
|
+
* Note that any transaction using a relative timelock (nSequence < 0x80000000)
|
|
184
|
+
* also falls within the RBF range (nSequence < 0xFFFFFFFE), making it
|
|
185
|
+
* inherently replaceable. So don't set `rbf` to false if this is tx uses
|
|
186
|
+
* relative time locks.
|
|
187
|
+
*
|
|
179
188
|
* @returns A finalizer function to be used after signing the `psbt`.
|
|
180
189
|
* This function ensures that this input is properly finalized.
|
|
181
190
|
* The finalizer has this signature:
|
|
@@ -183,12 +192,13 @@ export declare function DescriptorsFactory(ecc: TinySecp256k1Interface): {
|
|
|
183
192
|
* `( { psbt, validate = true } : { psbt: Psbt; validate: boolean | undefined } ) => void`
|
|
184
193
|
*
|
|
185
194
|
*/
|
|
186
|
-
updatePsbtAsInput({ psbt, txHex, txId, value, vout }: {
|
|
195
|
+
updatePsbtAsInput({ psbt, txHex, txId, value, vout, rbf }: {
|
|
187
196
|
psbt: Psbt;
|
|
188
197
|
txHex?: string;
|
|
189
198
|
txId?: string;
|
|
190
199
|
value?: number;
|
|
191
200
|
vout: number;
|
|
201
|
+
rbf?: boolean;
|
|
192
202
|
}): ({ psbt, validate }: {
|
|
193
203
|
psbt: Psbt;
|
|
194
204
|
/** Runs further test on the validity of the signatures.
|
|
@@ -440,6 +450,7 @@ export declare function DescriptorsFactory(ecc: TinySecp256k1Interface): {
|
|
|
440
450
|
txId?: string;
|
|
441
451
|
value?: number;
|
|
442
452
|
vout: number;
|
|
453
|
+
rbf?: boolean;
|
|
443
454
|
}): number;
|
|
444
455
|
/**
|
|
445
456
|
* Sets this output as an input of the provided `psbt` and updates the
|
|
@@ -458,6 +469,14 @@ export declare function DescriptorsFactory(ecc: TinySecp256k1Interface): {
|
|
|
458
469
|
*
|
|
459
470
|
* When unsure, always use `txHex`, and skip `txId` and `value` for safety.
|
|
460
471
|
*
|
|
472
|
+
* Use `rbf` to mark whether this tx can be replaced with another with
|
|
473
|
+
* higher fee while being in the mempool. Note that a tx will automatically
|
|
474
|
+
* be marked as replacable if a single input requests it.
|
|
475
|
+
* Note that any transaction using a relative timelock (nSequence < 0x80000000)
|
|
476
|
+
* also falls within the RBF range (nSequence < 0xFFFFFFFE), making it
|
|
477
|
+
* inherently replaceable. So don't set `rbf` to false if this is tx uses
|
|
478
|
+
* relative time locks.
|
|
479
|
+
*
|
|
461
480
|
* @returns A finalizer function to be used after signing the `psbt`.
|
|
462
481
|
* This function ensures that this input is properly finalized.
|
|
463
482
|
* The finalizer has this signature:
|
|
@@ -465,12 +484,13 @@ export declare function DescriptorsFactory(ecc: TinySecp256k1Interface): {
|
|
|
465
484
|
* `( { psbt, validate = true } : { psbt: Psbt; validate: boolean | undefined } ) => void`
|
|
466
485
|
*
|
|
467
486
|
*/
|
|
468
|
-
updatePsbtAsInput({ psbt, txHex, txId, value, vout }: {
|
|
487
|
+
updatePsbtAsInput({ psbt, txHex, txId, value, vout, rbf }: {
|
|
469
488
|
psbt: Psbt;
|
|
470
489
|
txHex?: string;
|
|
471
490
|
txId?: string;
|
|
472
491
|
value?: number;
|
|
473
492
|
vout: number;
|
|
493
|
+
rbf?: boolean;
|
|
474
494
|
}): ({ psbt, validate }: {
|
|
475
495
|
psbt: Psbt;
|
|
476
496
|
/** Runs further test on the validity of the signatures.
|
package/dist/descriptors.js
CHANGED
|
@@ -905,6 +905,14 @@ function DescriptorsFactory(ecc) {
|
|
|
905
905
|
*
|
|
906
906
|
* When unsure, always use `txHex`, and skip `txId` and `value` for safety.
|
|
907
907
|
*
|
|
908
|
+
* Use `rbf` to mark whether this tx can be replaced with another with
|
|
909
|
+
* higher fee while being in the mempool. Note that a tx will automatically
|
|
910
|
+
* be marked as replacable if a single input requests it.
|
|
911
|
+
* Note that any transaction using a relative timelock (nSequence < 0x80000000)
|
|
912
|
+
* also falls within the RBF range (nSequence < 0xFFFFFFFE), making it
|
|
913
|
+
* inherently replaceable. So don't set `rbf` to false if this is tx uses
|
|
914
|
+
* relative time locks.
|
|
915
|
+
*
|
|
908
916
|
* @returns A finalizer function to be used after signing the `psbt`.
|
|
909
917
|
* This function ensures that this input is properly finalized.
|
|
910
918
|
* The finalizer has this signature:
|
|
@@ -912,8 +920,8 @@ function DescriptorsFactory(ecc) {
|
|
|
912
920
|
* `( { psbt, validate = true } : { psbt: Psbt; validate: boolean | undefined } ) => void`
|
|
913
921
|
*
|
|
914
922
|
*/
|
|
915
|
-
updatePsbtAsInput({ psbt, txHex, txId, value, vout //vector output index
|
|
916
|
-
|
|
923
|
+
updatePsbtAsInput({ psbt, txHex, txId, value, vout, //vector output index
|
|
924
|
+
rbf = true }) {
|
|
917
925
|
if (txHex === undefined) {
|
|
918
926
|
console.warn(`Warning: missing txHex may allow fee attacks`);
|
|
919
927
|
}
|
|
@@ -934,7 +942,8 @@ function DescriptorsFactory(ecc) {
|
|
|
934
942
|
scriptPubKey: this.getScriptPubKey(),
|
|
935
943
|
isSegwit,
|
|
936
944
|
witnessScript: this.getWitnessScript(),
|
|
937
|
-
redeemScript: this.getRedeemScript()
|
|
945
|
+
redeemScript: this.getRedeemScript(),
|
|
946
|
+
rbf
|
|
938
947
|
});
|
|
939
948
|
const finalizer = ({ psbt, validate = true }) => this.finalizePsbtInput({ index, psbt, validate });
|
|
940
949
|
return finalizer;
|
|
@@ -1072,16 +1081,20 @@ function DescriptorsFactory(ecc) {
|
|
|
1072
1081
|
scriptPubKey = out.script;
|
|
1073
1082
|
}
|
|
1074
1083
|
const locktime = this.getLockTime() || 0;
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
sequence
|
|
1084
|
+
const sequence = this.getSequence();
|
|
1085
|
+
//We don't know whether the user opted for RBF or not. So check that
|
|
1086
|
+
//at least one of the 2 sequences matches.
|
|
1087
|
+
const sequenceNoRBF = sequence !== undefined
|
|
1088
|
+
? sequence
|
|
1089
|
+
: locktime === 0
|
|
1090
|
+
? 0xffffffff
|
|
1091
|
+
: 0xfffffffe;
|
|
1092
|
+
const sequenceRBF = sequence !== undefined ? sequence : 0xfffffffd;
|
|
1080
1093
|
const eqBuffers = (buf1, buf2) => buf1 instanceof Buffer && buf2 instanceof Buffer
|
|
1081
1094
|
? Buffer.compare(buf1, buf2) === 0
|
|
1082
1095
|
: buf1 === buf2;
|
|
1083
1096
|
if (Buffer.compare(scriptPubKey, this.getScriptPubKey()) !== 0 ||
|
|
1084
|
-
|
|
1097
|
+
(sequenceRBF !== inputSequence && sequenceNoRBF !== inputSequence) ||
|
|
1085
1098
|
locktime !== psbt.locktime ||
|
|
1086
1099
|
!eqBuffers(this.getWitnessScript(), input.witnessScript) ||
|
|
1087
1100
|
!eqBuffers(this.getRedeemScript(), input.redeemScript)) {
|
package/dist/psbt.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export declare function finalScriptsFuncFactory(scriptSatisfaction: Buffer, netw
|
|
|
21
21
|
/**
|
|
22
22
|
* Important: Read comments on descriptor.updatePsbt regarding not passing txHex
|
|
23
23
|
*/
|
|
24
|
-
export declare function updatePsbt({ psbt, vout, txHex, txId, value, sequence, locktime, keysInfo, scriptPubKey, isSegwit, witnessScript, redeemScript }: {
|
|
24
|
+
export declare function updatePsbt({ psbt, vout, txHex, txId, value, sequence, locktime, keysInfo, scriptPubKey, isSegwit, witnessScript, redeemScript, rbf }: {
|
|
25
25
|
psbt: Psbt;
|
|
26
26
|
vout: number;
|
|
27
27
|
txHex?: string;
|
|
@@ -34,5 +34,6 @@ export declare function updatePsbt({ psbt, vout, txHex, txId, value, sequence, l
|
|
|
34
34
|
isSegwit: boolean;
|
|
35
35
|
witnessScript: Buffer | undefined;
|
|
36
36
|
redeemScript: Buffer | undefined;
|
|
37
|
+
rbf: boolean;
|
|
37
38
|
}): number;
|
|
38
39
|
export {};
|
package/dist/psbt.js
CHANGED
|
@@ -86,8 +86,10 @@ exports.finalScriptsFuncFactory = finalScriptsFuncFactory;
|
|
|
86
86
|
/**
|
|
87
87
|
* Important: Read comments on descriptor.updatePsbt regarding not passing txHex
|
|
88
88
|
*/
|
|
89
|
-
function updatePsbt({ psbt, vout, txHex, txId, value, sequence, locktime, keysInfo, scriptPubKey, isSegwit, witnessScript, redeemScript }) {
|
|
89
|
+
function updatePsbt({ psbt, vout, txHex, txId, value, sequence, locktime, keysInfo, scriptPubKey, isSegwit, witnessScript, redeemScript, rbf }) {
|
|
90
90
|
//Some data-sanity checks:
|
|
91
|
+
if (sequence !== undefined && rbf && sequence > 0xfffffffd)
|
|
92
|
+
throw new Error(`Error: incompatible sequence and rbf settings`);
|
|
91
93
|
if (!isSegwit && txHex === undefined)
|
|
92
94
|
throw new Error(`Error: txHex is mandatory for Non-Segwit inputs`);
|
|
93
95
|
if (isSegwit &&
|
|
@@ -129,13 +131,23 @@ function updatePsbt({ psbt, vout, txHex, txId, value, sequence, locktime, keysIn
|
|
|
129
131
|
// this input's sequence < 0xffffffff
|
|
130
132
|
if (sequence === undefined) {
|
|
131
133
|
//NOTE: if sequence is undefined, bitcoinjs-lib uses 0xffffffff as default
|
|
132
|
-
sequence = 0xfffffffe;
|
|
134
|
+
sequence = rbf ? 0xfffffffd : 0xfffffffe;
|
|
133
135
|
}
|
|
134
136
|
else if (sequence > 0xfffffffe) {
|
|
135
137
|
throw new Error(`Error: incompatible sequence: ${sequence} and locktime: ${locktime}`);
|
|
136
138
|
}
|
|
139
|
+
if (sequence === undefined && rbf)
|
|
140
|
+
sequence = 0xfffffffd;
|
|
137
141
|
psbt.setLocktime(locktime);
|
|
138
142
|
}
|
|
143
|
+
else {
|
|
144
|
+
if (sequence === undefined) {
|
|
145
|
+
if (rbf)
|
|
146
|
+
sequence = 0xfffffffd;
|
|
147
|
+
else
|
|
148
|
+
sequence = 0xffffffff;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
139
151
|
const input = {
|
|
140
152
|
hash: reverseBuffer(Buffer.from(txId, 'hex')),
|
|
141
153
|
index: vout
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@bitcoinerlab/descriptors",
|
|
3
3
|
"description": "This library parses and creates Bitcoin Miniscript Descriptors and generates Partially Signed Bitcoin Transactions (PSBTs). It provides PSBT finalizers and signers for single-signature, BIP32 and Hardware Wallets.",
|
|
4
4
|
"homepage": "https://github.com/bitcoinerlab/descriptors",
|
|
5
|
-
"version": "2.
|
|
5
|
+
"version": "2.2.0",
|
|
6
6
|
"author": "Jose-Luis Landabaso",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
"yargs": "^17.7.2"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@bitcoinerlab/miniscript": "^1.
|
|
71
|
-
"@bitcoinerlab/secp256k1": "^1.
|
|
70
|
+
"@bitcoinerlab/miniscript": "^1.4.0",
|
|
71
|
+
"@bitcoinerlab/secp256k1": "^1.1.1",
|
|
72
72
|
"bip32": "^4.0.0",
|
|
73
73
|
"bitcoinjs-lib": "^6.1.3",
|
|
74
74
|
"ecpair": "^2.1.0",
|