@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.
- package/browser/_version.d.ts +1 -1
- package/browser/event/NetEvent.d.ts +3 -3
- package/browser/generators/builders/LegacyCalldataGenerator.d.ts +8 -0
- package/browser/index.js +1 -1
- package/browser/keypair/Address.d.ts +1 -0
- package/browser/keypair/AddressVerificator.d.ts +2 -3
- package/browser/opnet.d.ts +1 -0
- package/browser/transaction/shared/TweakedTransaction.d.ts +9 -0
- package/browser/utxo/interfaces/IUTXO.d.ts +3 -0
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/event/NetEvent.d.ts +3 -3
- package/build/event/NetEvent.js +3 -3
- package/build/generators/builders/LegacyCalldataGenerator.d.ts +8 -0
- package/build/generators/builders/LegacyCalldataGenerator.js +75 -0
- package/build/keypair/Address.d.ts +1 -0
- package/build/keypair/Address.js +3 -0
- package/build/keypair/AddressVerificator.d.ts +2 -3
- package/build/keypair/AddressVerificator.js +13 -3
- package/build/opnet.d.ts +1 -0
- package/build/opnet.js +1 -0
- package/build/transaction/builders/TransactionBuilder.js +1 -1
- package/build/transaction/shared/TweakedTransaction.d.ts +9 -0
- package/build/transaction/shared/TweakedTransaction.js +93 -3
- package/build/utxo/interfaces/IUTXO.d.ts +3 -0
- package/package.json +1 -1
- package/src/_version.ts +1 -1
- package/src/event/NetEvent.ts +2 -2
- package/src/generators/builders/LegacyCalldataGenerator.ts +141 -0
- package/src/keypair/Address.ts +8 -0
- package/src/keypair/AddressVerificator.ts +22 -3
- package/src/opnet.ts +1 -0
- package/src/transaction/builders/TransactionBuilder.ts +1 -1
- package/src/transaction/shared/TweakedTransaction.ts +157 -2
- 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 =
|
|
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 {
|