@btc-vision/transaction 1.0.118 → 1.0.119

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.
Files changed (35) hide show
  1. package/browser/_version.d.ts +1 -1
  2. package/browser/event/NetEvent.d.ts +3 -3
  3. package/browser/generators/builders/LegacyCalldataGenerator.d.ts +8 -0
  4. package/browser/index.js +1 -1
  5. package/browser/keypair/Address.d.ts +1 -0
  6. package/browser/keypair/AddressVerificator.d.ts +2 -3
  7. package/browser/opnet.d.ts +1 -0
  8. package/browser/transaction/shared/TweakedTransaction.d.ts +9 -0
  9. package/browser/utxo/interfaces/IUTXO.d.ts +3 -0
  10. package/build/_version.d.ts +1 -1
  11. package/build/_version.js +1 -1
  12. package/build/event/NetEvent.d.ts +3 -3
  13. package/build/event/NetEvent.js +3 -3
  14. package/build/generators/builders/LegacyCalldataGenerator.d.ts +8 -0
  15. package/build/generators/builders/LegacyCalldataGenerator.js +75 -0
  16. package/build/keypair/Address.d.ts +1 -0
  17. package/build/keypair/Address.js +3 -0
  18. package/build/keypair/AddressVerificator.d.ts +2 -3
  19. package/build/keypair/AddressVerificator.js +13 -3
  20. package/build/opnet.d.ts +1 -0
  21. package/build/opnet.js +1 -0
  22. package/build/transaction/builders/TransactionBuilder.js +1 -1
  23. package/build/transaction/shared/TweakedTransaction.d.ts +9 -0
  24. package/build/transaction/shared/TweakedTransaction.js +93 -3
  25. package/build/utxo/interfaces/IUTXO.d.ts +3 -0
  26. package/package.json +1 -1
  27. package/src/_version.ts +1 -1
  28. package/src/event/NetEvent.ts +2 -2
  29. package/src/generators/builders/LegacyCalldataGenerator.ts +141 -0
  30. package/src/keypair/Address.ts +8 -0
  31. package/src/keypair/AddressVerificator.ts +22 -3
  32. package/src/opnet.ts +1 -0
  33. package/src/transaction/builders/TransactionBuilder.ts +1 -1
  34. package/src/transaction/shared/TweakedTransaction.ts +157 -2
  35. package/src/utxo/interfaces/IUTXO.ts +3 -0
package/src/opnet.ts CHANGED
@@ -6,6 +6,7 @@ export * from './bytecode/Compressor.js';
6
6
  /** Generators */
7
7
  export * from './generators/Generator.js';
8
8
  export * from './generators/builders/CalldataGenerator.js';
9
+ export * from './generators/builders/LegacyCalldataGenerator.js';
9
10
  export * from './generators/builders/DeploymentGenerator.js';
10
11
  export * from './generators/builders/CustomGenerator.js';
11
12
  export * from './generators/builders/MultiSignGenerator.js';
@@ -37,7 +37,7 @@ export abstract class TransactionBuilder<T extends TransactionType> extends Twea
37
37
  //opcodes.OP_VERIFY, - verify that this is not needed.
38
38
  ]);
39
39
 
40
- public static readonly MINIMUM_DUST: bigint = 330n;
40
+ public static readonly MINIMUM_DUST: bigint = 50n;
41
41
 
42
42
  public abstract readonly type: T;
43
43
  public readonly logColor: string = '#785def';
@@ -1,11 +1,16 @@
1
1
  import { Logger } from '@btc-vision/logger';
2
2
  import {
3
+ address as bitAddress,
4
+ crypto as bitCrypto,
5
+ getFinalScripts,
3
6
  Network,
7
+ opcodes,
4
8
  Payment,
5
9
  payments,
6
10
  Psbt,
7
11
  PsbtInput,
8
12
  PsbtInputExtended,
13
+ script,
9
14
  Signer,
10
15
  Transaction,
11
16
  } from 'bitcoinjs-lib';
@@ -14,7 +19,7 @@ import { ECPairInterface } from 'ecpair';
14
19
  import { toXOnly } from 'bitcoinjs-lib/src/psbt/bip371.js';
15
20
  import { UTXO } from '../../utxo/interfaces/IUTXO.js';
16
21
  import { TapLeafScript } from '../interfaces/Tap.js';
17
- import { AddressVerificator } from '../../keypair/AddressVerificator.js';
22
+ import { AddressTypes, AddressVerificator } from '../../keypair/AddressVerificator.js';
18
23
  import { ChainId } from '../../network/ChainId.js';
19
24
  import { varuint } from 'bitcoinjs-lib/src/bufferutils.js';
20
25
 
@@ -474,6 +479,8 @@ export abstract class TweakedTransaction extends Logger {
474
479
  await Promise.all(promises);
475
480
  }
476
481
 
482
+ transaction.finalizeInput(0, this.customFinalizerP2SH);
483
+
477
484
  try {
478
485
  transaction.finalizeAllInputs();
479
486
 
@@ -536,6 +543,65 @@ export abstract class TweakedTransaction extends Logger {
536
543
  return TweakedSigner.tweakSigner(signer as unknown as ECPairInterface, settings);
537
544
  }
538
545
 
546
+ protected generateP2SHRedeemScript(customWitnessScript: Buffer): Buffer | undefined {
547
+ const p2wsh = payments.p2wsh({
548
+ redeem: { output: customWitnessScript },
549
+ network: this.network,
550
+ });
551
+
552
+ // Step 2: Wrap the P2WSH inside a P2SH (Pay-to-Script-Hash)
553
+ const p2sh = payments.p2sh({
554
+ redeem: p2wsh,
555
+ network: this.network,
556
+ });
557
+
558
+ return p2sh.output;
559
+ }
560
+
561
+ protected generateP2SHRedeemScriptLegacy(inputAddr: string):
562
+ | {
563
+ redeemScript: Buffer;
564
+ outputScript: Buffer;
565
+ }
566
+ | undefined {
567
+ const pubKeyHash = bitCrypto.hash160(this.signer.publicKey);
568
+ const redeemScript: Buffer = script.compile([
569
+ opcodes.OP_DUP,
570
+ opcodes.OP_HASH160,
571
+ pubKeyHash,
572
+ opcodes.OP_EQUALVERIFY,
573
+ opcodes.OP_CHECKSIG,
574
+ ]);
575
+
576
+ const redeemScriptHash = bitCrypto.hash160(redeemScript);
577
+ const outputScript = script.compile([
578
+ opcodes.OP_HASH160,
579
+ redeemScriptHash,
580
+ opcodes.OP_EQUAL,
581
+ ]);
582
+
583
+ const p2wsh = payments.p2wsh({
584
+ redeem: { output: redeemScript }, // Use the custom redeem script
585
+ network: this.network,
586
+ });
587
+
588
+ // Step 3: Wrap the P2WSH in a P2SH
589
+ const p2sh = payments.p2sh({
590
+ redeem: p2wsh, // The P2WSH is wrapped inside the P2SH
591
+ network: this.network,
592
+ });
593
+
594
+ const address = bitAddress.fromOutputScript(outputScript, this.network);
595
+ if (address === inputAddr && p2sh.redeem && p2sh.redeem.output) {
596
+ return {
597
+ redeemScript,
598
+ outputScript: p2sh.redeem.output,
599
+ };
600
+ }
601
+
602
+ return;
603
+ }
604
+
539
605
  /**
540
606
  * Generate the PSBT input extended
541
607
  * @param {UTXO} utxo The UTXO
@@ -547,13 +613,60 @@ export abstract class TweakedTransaction extends Logger {
547
613
  const input: PsbtInputExtended = {
548
614
  hash: utxo.transactionId,
549
615
  index: utxo.outputIndex,
616
+ sequence: this.sequence,
550
617
  witnessUtxo: {
551
618
  value: Number(utxo.value),
552
619
  script: Buffer.from(utxo.scriptPubKey.hex, 'hex'),
553
620
  },
554
- sequence: this.sequence,
555
621
  };
556
622
 
623
+ if (utxo.scriptPubKey.address) {
624
+ // auto detect for potential p2sh utxos
625
+ try {
626
+ const addressType: AddressTypes | null = AddressVerificator.detectAddressType(
627
+ utxo.scriptPubKey.address,
628
+ this.network,
629
+ );
630
+
631
+ if (addressType === AddressTypes.P2SH_OR_P2SH_P2WPKH) {
632
+ // We can automatically reconstruct the redeem script.
633
+ const redeemScript = this.generateP2SHRedeemScriptLegacy(
634
+ utxo.scriptPubKey.address,
635
+ );
636
+
637
+ if (!redeemScript) {
638
+ throw new Error('Failed to generate redeem script');
639
+ }
640
+
641
+ input.redeemScript = redeemScript.outputScript;
642
+ input.witnessScript = redeemScript.redeemScript;
643
+ }
644
+ } catch (e) {
645
+ this.error(`Failed to detect address type for ${utxo.scriptPubKey.address} - ${e}`);
646
+ }
647
+ }
648
+
649
+ // LEGACY P2SH SUPPORT
650
+ if (utxo.nonWitnessUtxo) {
651
+ input.nonWitnessUtxo = Buffer.isBuffer(utxo.nonWitnessUtxo)
652
+ ? utxo.nonWitnessUtxo
653
+ : Buffer.from(utxo.nonWitnessUtxo, 'hex');
654
+ }
655
+
656
+ // SEGWIT SUPPORT
657
+ if (utxo.redeemScript) {
658
+ input.redeemScript = Buffer.isBuffer(utxo.redeemScript)
659
+ ? utxo.redeemScript
660
+ : Buffer.from(utxo.redeemScript, 'hex');
661
+
662
+ if (utxo.witnessScript) {
663
+ input.witnessScript = Buffer.isBuffer(utxo.witnessScript)
664
+ ? utxo.witnessScript
665
+ : Buffer.from(utxo.witnessScript, 'hex');
666
+ }
667
+ }
668
+
669
+ // TAPROOT.
557
670
  if (this.sighashTypes) {
558
671
  const inputSign = TweakedTransaction.calculateSignHash(this.sighashTypes);
559
672
  if (inputSign) input.sighashType = inputSign;
@@ -580,4 +693,46 @@ export abstract class TweakedTransaction extends Logger {
580
693
 
581
694
  return input;
582
695
  }
696
+
697
+ protected customFinalizerP2SH = (
698
+ inputIndex: number, // Which input is it?
699
+ input: PsbtInput, // The PSBT input contents
700
+ scriptA: Buffer, // The "meaningful" locking script Buffer (redeemScript for P2SH etc.)
701
+ isSegwit: boolean, // Is it segwit?
702
+ isP2SH: boolean, // Is it P2SH?
703
+ isP2WSH: boolean,
704
+ ): {
705
+ finalScriptSig: Buffer | undefined;
706
+ finalScriptWitness: Buffer | undefined;
707
+ } => {
708
+ const inputDecoded = this.inputs[inputIndex];
709
+ if (isP2SH && input.partialSig && inputDecoded && inputDecoded.redeemScript) {
710
+ const signatures = input.partialSig.map((sig) => sig.signature);
711
+
712
+ /*const fakeSignature = Buffer.from([
713
+ 0x30,
714
+ 0x45, // DER prefix: 0x30 (Compound), 0x45 (length = 69 bytes)
715
+ 0x02,
716
+ 0x20, // Integer marker: 0x02 (integer), 0x20 (length = 32 bytes)
717
+ ...Buffer.alloc(32, 0x00), // 32-byte fake 'r' value (all zeros)
718
+ 0x02,
719
+ 0x21, // Integer marker: 0x02 (integer), 0x21 (length = 33 bytes)
720
+ ...Buffer.alloc(33, 0x00), // 33-byte fake 's' value (all zeros)
721
+ 0x01, // SIGHASH_ALL flag (0x01)
722
+ ]);*/
723
+
724
+ const scriptSig = script.compile([
725
+ ...signatures,
726
+ //fakeSignature,
727
+ inputDecoded.redeemScript,
728
+ ]);
729
+
730
+ return {
731
+ finalScriptSig: scriptSig, // Manually set the final scriptSig
732
+ finalScriptWitness: undefined, // Manually set the final scriptWitness
733
+ };
734
+ }
735
+
736
+ return getFinalScripts(inputIndex, input, scriptA, isSegwit, isP2SH, isP2WSH);
737
+ };
583
738
  }
@@ -5,6 +5,9 @@ export interface UTXO {
5
5
  readonly outputIndex: number;
6
6
  readonly value: bigint;
7
7
  readonly scriptPubKey: ScriptPubKey;
8
+ redeemScript?: string | Buffer;
9
+ witnessScript?: string | Buffer;
10
+ nonWitnessUtxo?: string | Buffer;
8
11
  }
9
12
 
10
13
  export interface FetchUTXOParams {