@@ -17,41 +17,6 @@ const bip32 = BIP32Factory(ecc);
1717const ECPair = ECPairFactory ( ecc ) ;
1818
1919describe ( 'bitcoinjs-lib (transaction with taproot)' , ( ) => {
20- it ( 'can create (and broadcast via 3PBP) a taproot keyspend Transaction' , async ( ) => {
21- const myKey = bip32 . fromSeed ( rng ( 64 ) , regtest ) ;
22-
23- const output = createKeySpendOutput ( myKey . publicKey ) ;
24- const address = bitcoin . address . fromOutputScript ( output , regtest ) ;
25- // amount from faucet
26- const amount = 42e4 ;
27- // amount to send
28- const sendAmount = amount - 1e4 ;
29- // get faucet
30- const unspent = await regtestUtils . faucetComplex ( output , amount ) ;
31-
32- const tx = createSigned (
33- myKey ,
34- unspent . txId ,
35- unspent . vout ,
36- sendAmount ,
37- [ output ] ,
38- [ amount ] ,
39- ) ;
40-
41- const hex = tx . toHex ( ) ;
42- // console.log('Valid tx sent from:');
43- // console.log(address);
44- // console.log('tx hex:');
45- // console.log(hex);
46- await regtestUtils . broadcast ( hex ) ;
47- await regtestUtils . verify ( {
48- txId : tx . getId ( ) ,
49- address,
50- vout : 0 ,
51- value : sendAmount ,
52- } ) ;
53- } ) ;
54-
5520 it ( 'can create (and broadcast via 3PBP) a taproot key-path spend Transaction' , async ( ) => {
5621 const internalKey = bip32 . fromSeed ( rng ( 64 ) , regtest ) ;
5722 const p2pkhKey = bip32 . fromSeed ( rng ( 64 ) , regtest ) ;
@@ -593,83 +558,6 @@ function buildLeafIndexFinalizer(
593558 } ;
594559}
595560
596- // Order of the curve (N) - 1
597- const N_LESS_1 = Buffer . from (
598- 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140' ,
599- 'hex' ,
600- ) ;
601- // 1 represented as 32 bytes BE
602- const ONE = Buffer . from (
603- '0000000000000000000000000000000000000000000000000000000000000001' ,
604- 'hex' ,
605- ) ;
606-
607- // Function for creating a tweaked p2tr key-spend only address
608- // (This is recommended by BIP341)
609- function createKeySpendOutput ( publicKey : Buffer ) : Buffer {
610- // x-only pubkey (remove 1 byte y parity)
611- const myXOnlyPubkey = toXOnly ( publicKey ) ;
612- const commitHash = bitcoin . crypto . taggedHash ( 'TapTweak' , myXOnlyPubkey ) ;
613- const tweakResult = ecc . xOnlyPointAddTweak ( myXOnlyPubkey , commitHash ) ;
614- if ( tweakResult === null ) throw new Error ( 'Invalid Tweak' ) ;
615- const { xOnlyPubkey : tweaked } = tweakResult ;
616- // scriptPubkey
617- return Buffer . concat ( [
618- // witness v1, PUSH_DATA 32 bytes
619- Buffer . from ( [ 0x51 , 0x20 ] ) ,
620- // x-only tweaked pubkey
621- tweaked ,
622- ] ) ;
623- }
624-
625- // Function for signing for a tweaked p2tr key-spend only address
626- // (Required for the above address)
627- interface KeyPair {
628- publicKey : Buffer ;
629- privateKey ?: Buffer ;
630- }
631- function signTweaked ( messageHash : Buffer , key : KeyPair ) : Uint8Array {
632- const privateKey =
633- key . publicKey [ 0 ] === 2
634- ? key . privateKey
635- : ecc . privateAdd ( ecc . privateSub ( N_LESS_1 , key . privateKey ! ) ! , ONE ) ! ;
636- const tweakHash = bitcoin . crypto . taggedHash (
637- 'TapTweak' ,
638- toXOnly ( key . publicKey ) ,
639- ) ;
640- const newPrivateKey = ecc . privateAdd ( privateKey ! , tweakHash ) ;
641- if ( newPrivateKey === null ) throw new Error ( 'Invalid Tweak' ) ;
642- return ecc . signSchnorr ( messageHash , newPrivateKey , Buffer . alloc ( 32 ) ) ;
643- }
644-
645- // Function for creating signed tx
646- function createSigned (
647- key : KeyPair ,
648- txid : string ,
649- vout : number ,
650- amountToSend : number ,
651- scriptPubkeys : Buffer [ ] ,
652- values : number [ ] ,
653- ) : bitcoin . Transaction {
654- const tx = new bitcoin . Transaction ( ) ;
655- tx . version = 2 ;
656- // Add input
657- tx . addInput ( Buffer . from ( txid , 'hex' ) . reverse ( ) , vout ) ;
658- // Add output
659- tx . addOutput ( scriptPubkeys [ 0 ] , amountToSend ) ;
660- const sighash = tx . hashForWitnessV1 (
661- 0 , // which input
662- scriptPubkeys , // All previous outputs of all inputs
663- values , // All previous values of all inputs
664- bitcoin . Transaction . SIGHASH_DEFAULT , // sighash flag, DEFAULT is schnorr-only (DEFAULT == ALL)
665- ) ;
666- const signature = Buffer . from ( signTweaked ( sighash , key ) ) ;
667- // witness stack for keypath spend is just the signature.
668- // If sighash is not SIGHASH_DEFAULT (ALL) then you must add 1 byte with sighash value
669- tx . ins [ 0 ] . witness = [ signature ] ;
670- return tx ;
671- }
672-
673561// This logic will be extracted to ecpair
674562function tweakSigner ( signer : bitcoin . Signer , opts : any = { } ) : bitcoin . Signer {
675563 // eslint-disable-next-line @typescript-eslint/ban-ts-comment
0 commit comments