@caravan/psbt 1.4.3 → 1.6.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/dist/index.d.ts CHANGED
@@ -209,6 +209,65 @@ declare class PsbtV2 extends PsbtV2Maps {
209
209
  * validate the current state of the psbt.
210
210
  */
211
211
  private validate;
212
+ /**
213
+ * Sets the sequence number for a specific input in the transaction.
214
+ *
215
+ * This private helper method is crucial for implementing RBF and other
216
+ * sequence-based transaction features. It writes the provided sequence
217
+ * number as a 32-bit little-endian unsigned integer and stores it in the
218
+ * appropriate input's map using the PSBT_IN_SEQUENCE key.
219
+ *
220
+ * The sequence number has multiple uses in Bitcoin transactions:
221
+ * 1. Signaling RBF (values < 0xfffffffe)
222
+ * 2. Enabling nLockTime (values < 0xffffffff)
223
+ * 3. Relative timelock with BIP68 (if bit 31 is not set)
224
+ *
225
+ * According to BIP125 (Opt-in Full Replace-by-Fee Signaling):
226
+ *
227
+ * - For a transaction to be considered opt-in RBF, it must have at least
228
+ * one input with a sequence number < 0xfffffffe.
229
+ * - The recommended sequence for RBF is 0xffffffff-2 (0xfffffffd).
230
+ *
231
+ * Sequence number meanings:
232
+ * - = 0xffffffff: Then the transaction is final no matter the nLockTime.
233
+ * - < 0xfffffffe: Transaction signals for RBF.
234
+ * - < 0xefffffff : Then the transaction signals BIP68 relative locktime.
235
+ *
236
+ * For using nLocktime along with Opt-in RBF, the sequence value
237
+ * should be between 0xf0000000 and 0xfffffffd.
238
+ *
239
+ * Care should be taken when setting sequence numbers to ensure the desired
240
+ * transaction properties are correctly signaled. Improper use can lead to
241
+ * unexpected transaction behavior or rejection by the network.
242
+ *
243
+ * References:
244
+ * - BIP125: Opt-in Full Replace-by-Fee Signaling
245
+ * https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki
246
+ * - BIP68: Relative lock-time using consensus-enforced sequence numbers
247
+ * https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki
248
+ */
249
+ setInputSequence(inputIndex: number, sequence: number): void;
250
+ /**
251
+ * Checks if the transaction signals Replace-by-Fee (RBF).
252
+ *
253
+ * This method determines whether the transaction is eligible for RBF by
254
+ * examining the sequence numbers of all inputs. As per BIP125, a transaction
255
+ * is considered to have opted in to RBF if it contains at least one input
256
+ * with a sequence number less than (0xffffffff - 1).
257
+ *
258
+ * Return value:
259
+ * - true: If any input has a sequence number < 0xfffffffe, indicating RBF.
260
+ * - false: If all inputs have sequence numbers >= 0xfffffffe, indicating no RBF.
261
+ *
262
+ * This method is useful for wallets, block explorers, or any service that
263
+ * needs to determine if a transaction can potentially be replaced before
264
+ * confirmation.
265
+ *
266
+ * References:
267
+ * - BIP125: Opt-in Full Replace-by-Fee Signaling
268
+ * https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki
269
+ */
270
+ get isRBFSignaled(): boolean;
212
271
  /**
213
272
  * This method is provided for compatibility issues and probably shouldn't be
214
273
  * used since a PsbtV2 with PSBT_GLOBAL_TX_VERSION = 1 is BIP0370
package/dist/index.js CHANGED
@@ -789,6 +789,81 @@ var PsbtV2 = class _PsbtV2 extends PsbtV2Maps {
789
789
  }
790
790
  }
791
791
  }
792
+ /**
793
+ * Sets the sequence number for a specific input in the transaction.
794
+ *
795
+ * This private helper method is crucial for implementing RBF and other
796
+ * sequence-based transaction features. It writes the provided sequence
797
+ * number as a 32-bit little-endian unsigned integer and stores it in the
798
+ * appropriate input's map using the PSBT_IN_SEQUENCE key.
799
+ *
800
+ * The sequence number has multiple uses in Bitcoin transactions:
801
+ * 1. Signaling RBF (values < 0xfffffffe)
802
+ * 2. Enabling nLockTime (values < 0xffffffff)
803
+ * 3. Relative timelock with BIP68 (if bit 31 is not set)
804
+ *
805
+ * According to BIP125 (Opt-in Full Replace-by-Fee Signaling):
806
+ *
807
+ * - For a transaction to be considered opt-in RBF, it must have at least
808
+ * one input with a sequence number < 0xfffffffe.
809
+ * - The recommended sequence for RBF is 0xffffffff-2 (0xfffffffd).
810
+ *
811
+ * Sequence number meanings:
812
+ * - = 0xffffffff: Then the transaction is final no matter the nLockTime.
813
+ * - < 0xfffffffe: Transaction signals for RBF.
814
+ * - < 0xefffffff : Then the transaction signals BIP68 relative locktime.
815
+ *
816
+ * For using nLocktime along with Opt-in RBF, the sequence value
817
+ * should be between 0xf0000000 and 0xfffffffd.
818
+ *
819
+ * Care should be taken when setting sequence numbers to ensure the desired
820
+ * transaction properties are correctly signaled. Improper use can lead to
821
+ * unexpected transaction behavior or rejection by the network.
822
+ *
823
+ * References:
824
+ * - BIP125: Opt-in Full Replace-by-Fee Signaling
825
+ * https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki
826
+ * - BIP68: Relative lock-time using consensus-enforced sequence numbers
827
+ * https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki
828
+ */
829
+ setInputSequence(inputIndex, sequence) {
830
+ if (!this.isReadyForUpdater) {
831
+ throw new Error(
832
+ "PSBT is not ready for the Updater role. Sequence cannot be changed."
833
+ );
834
+ }
835
+ if (inputIndex < 0 || inputIndex >= this.PSBT_GLOBAL_INPUT_COUNT) {
836
+ throw new Error(`Input at index ${inputIndex} does not exist.`);
837
+ }
838
+ const bw = new import_bufio3.BufferWriter();
839
+ bw.writeU32(sequence);
840
+ this.inputMaps[inputIndex].set("10" /* PSBT_IN_SEQUENCE */, bw.render());
841
+ }
842
+ /**
843
+ * Checks if the transaction signals Replace-by-Fee (RBF).
844
+ *
845
+ * This method determines whether the transaction is eligible for RBF by
846
+ * examining the sequence numbers of all inputs. As per BIP125, a transaction
847
+ * is considered to have opted in to RBF if it contains at least one input
848
+ * with a sequence number less than (0xffffffff - 1).
849
+ *
850
+ * Return value:
851
+ * - true: If any input has a sequence number < 0xfffffffe, indicating RBF.
852
+ * - false: If all inputs have sequence numbers >= 0xfffffffe, indicating no RBF.
853
+ *
854
+ * This method is useful for wallets, block explorers, or any service that
855
+ * needs to determine if a transaction can potentially be replaced before
856
+ * confirmation.
857
+ *
858
+ * References:
859
+ * - BIP125: Opt-in Full Replace-by-Fee Signaling
860
+ * https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki
861
+ */
862
+ get isRBFSignaled() {
863
+ return this.PSBT_IN_SEQUENCE.some(
864
+ (seq) => seq !== null && seq < 4294967294
865
+ );
866
+ }
792
867
  /**
793
868
  * This method is provided for compatibility issues and probably shouldn't be
794
869
  * used since a PsbtV2 with PSBT_GLOBAL_TX_VERSION = 1 is BIP0370
@@ -93949,11 +94024,6 @@ var getHashForSignature = (psbt, inputIndex, inputAmount, sigHashFlag = import_b
93949
94024
  throw new Error("No redeem or witness script found for input.");
93950
94025
  };
93951
94026
  function translatePSBT(network, addressType, psbt, signingKeyDetails) {
93952
- if (addressType !== import_bitcoin4.P2SH) {
93953
- throw new Error(
93954
- "Unsupported addressType -- only P2SH is supported right now"
93955
- );
93956
- }
93957
94027
  const localPSBT = autoLoadPSBT(psbt, { network: (0, import_bitcoin4.networkData)(network) });
93958
94028
  if (localPSBT === null)
93959
94029
  return null;
@@ -93976,12 +94046,17 @@ function translatePSBT(network, addressType, psbt, signingKeyDetails) {
93976
94046
  function getUnchainedInputsFromPSBT(network, addressType, psbt) {
93977
94047
  return psbt.txInputs.map((input, index) => {
93978
94048
  const dataInput = psbt.data.inputs[index];
94049
+ const spendingScript = dataInput.witnessScript || dataInput.redeemScript;
94050
+ if (!dataInput?.nonWitnessUtxo && addressType === import_bitcoin4.P2WSH) {
94051
+ throw new Error(`Non-witness UTXO now required for P2WSH
94052
+ inputs to protect against large fee attack`);
94053
+ }
93979
94054
  const fundingTxHex = dataInput.nonWitnessUtxo.toString("hex");
93980
94055
  const fundingTx = import_bitcoinjs_lib_v63.Transaction.fromHex(fundingTxHex);
93981
94056
  const multisig = (0, import_bitcoin4.generateMultisigFromHex)(
93982
94057
  network,
93983
94058
  addressType,
93984
- dataInput.redeemScript.toString("hex")
94059
+ spendingScript.toString("hex")
93985
94060
  );
93986
94061
  return {
93987
94062
  amountSats: fundingTx.outs[input.index].value,
package/dist/index.mjs CHANGED
@@ -748,6 +748,81 @@ var PsbtV2 = class _PsbtV2 extends PsbtV2Maps {
748
748
  }
749
749
  }
750
750
  }
751
+ /**
752
+ * Sets the sequence number for a specific input in the transaction.
753
+ *
754
+ * This private helper method is crucial for implementing RBF and other
755
+ * sequence-based transaction features. It writes the provided sequence
756
+ * number as a 32-bit little-endian unsigned integer and stores it in the
757
+ * appropriate input's map using the PSBT_IN_SEQUENCE key.
758
+ *
759
+ * The sequence number has multiple uses in Bitcoin transactions:
760
+ * 1. Signaling RBF (values < 0xfffffffe)
761
+ * 2. Enabling nLockTime (values < 0xffffffff)
762
+ * 3. Relative timelock with BIP68 (if bit 31 is not set)
763
+ *
764
+ * According to BIP125 (Opt-in Full Replace-by-Fee Signaling):
765
+ *
766
+ * - For a transaction to be considered opt-in RBF, it must have at least
767
+ * one input with a sequence number < 0xfffffffe.
768
+ * - The recommended sequence for RBF is 0xffffffff-2 (0xfffffffd).
769
+ *
770
+ * Sequence number meanings:
771
+ * - = 0xffffffff: Then the transaction is final no matter the nLockTime.
772
+ * - < 0xfffffffe: Transaction signals for RBF.
773
+ * - < 0xefffffff : Then the transaction signals BIP68 relative locktime.
774
+ *
775
+ * For using nLocktime along with Opt-in RBF, the sequence value
776
+ * should be between 0xf0000000 and 0xfffffffd.
777
+ *
778
+ * Care should be taken when setting sequence numbers to ensure the desired
779
+ * transaction properties are correctly signaled. Improper use can lead to
780
+ * unexpected transaction behavior or rejection by the network.
781
+ *
782
+ * References:
783
+ * - BIP125: Opt-in Full Replace-by-Fee Signaling
784
+ * https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki
785
+ * - BIP68: Relative lock-time using consensus-enforced sequence numbers
786
+ * https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki
787
+ */
788
+ setInputSequence(inputIndex, sequence) {
789
+ if (!this.isReadyForUpdater) {
790
+ throw new Error(
791
+ "PSBT is not ready for the Updater role. Sequence cannot be changed."
792
+ );
793
+ }
794
+ if (inputIndex < 0 || inputIndex >= this.PSBT_GLOBAL_INPUT_COUNT) {
795
+ throw new Error(`Input at index ${inputIndex} does not exist.`);
796
+ }
797
+ const bw = new BufferWriter3();
798
+ bw.writeU32(sequence);
799
+ this.inputMaps[inputIndex].set("10" /* PSBT_IN_SEQUENCE */, bw.render());
800
+ }
801
+ /**
802
+ * Checks if the transaction signals Replace-by-Fee (RBF).
803
+ *
804
+ * This method determines whether the transaction is eligible for RBF by
805
+ * examining the sequence numbers of all inputs. As per BIP125, a transaction
806
+ * is considered to have opted in to RBF if it contains at least one input
807
+ * with a sequence number less than (0xffffffff - 1).
808
+ *
809
+ * Return value:
810
+ * - true: If any input has a sequence number < 0xfffffffe, indicating RBF.
811
+ * - false: If all inputs have sequence numbers >= 0xfffffffe, indicating no RBF.
812
+ *
813
+ * This method is useful for wallets, block explorers, or any service that
814
+ * needs to determine if a transaction can potentially be replaced before
815
+ * confirmation.
816
+ *
817
+ * References:
818
+ * - BIP125: Opt-in Full Replace-by-Fee Signaling
819
+ * https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki
820
+ */
821
+ get isRBFSignaled() {
822
+ return this.PSBT_IN_SEQUENCE.some(
823
+ (seq) => seq !== null && seq < 4294967294
824
+ );
825
+ }
751
826
  /**
752
827
  * This method is provided for compatibility issues and probably shouldn't be
753
828
  * used since a PsbtV2 with PSBT_GLOBAL_TX_VERSION = 1 is BIP0370
@@ -1166,6 +1241,7 @@ import {
1166
1241
  multisigSignatureBuffer,
1167
1242
  networkData,
1168
1243
  P2SH as P2SH2,
1244
+ P2WSH as P2WSH2,
1169
1245
  signatureNoSighashType
1170
1246
  } from "@caravan/bitcoin";
1171
1247
  import { Psbt as Psbt3, Transaction } from "bitcoinjs-lib-v6";
@@ -93927,11 +94003,6 @@ var getHashForSignature = (psbt, inputIndex, inputAmount, sigHashFlag = Transact
93927
94003
  throw new Error("No redeem or witness script found for input.");
93928
94004
  };
93929
94005
  function translatePSBT(network, addressType, psbt, signingKeyDetails) {
93930
- if (addressType !== P2SH2) {
93931
- throw new Error(
93932
- "Unsupported addressType -- only P2SH is supported right now"
93933
- );
93934
- }
93935
94006
  const localPSBT = autoLoadPSBT(psbt, { network: networkData(network) });
93936
94007
  if (localPSBT === null)
93937
94008
  return null;
@@ -93954,12 +94025,17 @@ function translatePSBT(network, addressType, psbt, signingKeyDetails) {
93954
94025
  function getUnchainedInputsFromPSBT(network, addressType, psbt) {
93955
94026
  return psbt.txInputs.map((input, index) => {
93956
94027
  const dataInput = psbt.data.inputs[index];
94028
+ const spendingScript = dataInput.witnessScript || dataInput.redeemScript;
94029
+ if (!dataInput?.nonWitnessUtxo && addressType === P2WSH2) {
94030
+ throw new Error(`Non-witness UTXO now required for P2WSH
94031
+ inputs to protect against large fee attack`);
94032
+ }
93957
94033
  const fundingTxHex = dataInput.nonWitnessUtxo.toString("hex");
93958
94034
  const fundingTx = Transaction.fromHex(fundingTxHex);
93959
94035
  const multisig = generateMultisigFromHex(
93960
94036
  network,
93961
94037
  addressType,
93962
- dataInput.redeemScript.toString("hex")
94038
+ spendingScript.toString("hex")
93963
94039
  );
93964
94040
  return {
93965
94041
  amountSats: fundingTx.outs[input.index].value,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caravan/psbt",
3
- "version": "1.4.3",
3
+ "version": "1.6.0",
4
4
  "description": "typescript library for working with PSBTs",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -51,6 +51,7 @@
51
51
  "author": "unchained capital",
52
52
  "license": "ISC",
53
53
  "devDependencies": {
54
+ "@caravan/bip32": "*",
54
55
  "@caravan/eslint-config": "*",
55
56
  "@caravan/multisig": "*",
56
57
  "@caravan/typescript-config": "*",