1
1
'use strict' ;
2
2
Object . defineProperty ( exports , '__esModule' , { value : true } ) ;
3
- exports . Psbt = void 0 ;
4
- const ecc = require ( 'tiny-secp256k1' ) ; // TODO: extract
3
+ exports . tweakSigner = exports . Psbt = void 0 ;
5
4
const ecpair_1 = require ( 'ecpair' ) ;
6
5
const bip174_1 = require ( 'bip174' ) ;
7
6
const varuint = require ( 'bip174/src/lib/converter/varint' ) ;
@@ -81,6 +80,7 @@ class Psbt {
81
80
// We will disable exporting the Psbt when unsafe sign is active.
82
81
// because it is not BIP174 compliant.
83
82
__UNSAFE_SIGN_NONSEGWIT : false ,
83
+ __EC_LIB : opts . eccLib ,
84
84
} ;
85
85
if ( this . data . inputs . length === 0 ) this . setVersion ( 2 ) ;
86
86
// Make data hidden when enumerating
@@ -106,39 +106,6 @@ class Psbt {
106
106
checkTxForDupeIns ( psbt . __CACHE . __TX , psbt . __CACHE ) ;
107
107
return psbt ;
108
108
}
109
- /**
110
- * Helper method for converting a normal Signer into a Taproot Signer.
111
- * Note that this helper method requires the Private Key of the Signer to be present.
112
- * Steps:
113
- * - if the Y coordinate of the Signer Public Key is odd then negate the Private Key
114
- * - tweak the private key with the provided hash (should be empty for key-path spending)
115
- * @param signer - a taproot signer object, the Private Key must be present
116
- * @param opts - tweak options
117
- * @returns a Signer having the Private and Public keys tweaked
118
- */
119
- static tweakSigner ( signer , opts = { } ) {
120
- let privateKey = signer . privateKey ;
121
- if ( ! privateKey ) {
122
- throw new Error ( 'Private key is required for tweaking signer!' ) ;
123
- }
124
- if ( signer . publicKey [ 0 ] === 3 ) {
125
- privateKey = ecc . privateNegate ( privateKey ) ;
126
- }
127
- const tweakedPrivateKey = ecc . privateAdd (
128
- privateKey ,
129
- ( 0 , taprootutils_1 . tapTweakHash ) (
130
- signer . publicKey . slice ( 1 , 33 ) ,
131
- opts . tweakHash ,
132
- ) ,
133
- ) ;
134
- if ( ! tweakedPrivateKey ) {
135
- throw new Error ( 'Invalid tweaked private key!' ) ;
136
- }
137
- const ECPair = ( 0 , ecpair_1 . ECPairFactory ) ( ecc ) ;
138
- return ECPair . fromPrivateKey ( Buffer . from ( tweakedPrivateKey ) , {
139
- network : opts . network ,
140
- } ) ;
141
- }
142
109
get inputCount ( ) {
143
110
return this . data . inputs . length ;
144
111
}
@@ -307,7 +274,7 @@ class Psbt {
307
274
range ( this . data . inputs . length ) . forEach ( idx => this . finalizeInput ( idx ) ) ;
308
275
return this ;
309
276
}
310
- finalizeInput ( inputIndex , finalScriptsFunc = getFinalScripts ) {
277
+ finalizeInput ( inputIndex , finalScriptsFunc ) {
311
278
const input = ( 0 , utils_1 . checkForInput ) ( this . data . inputs , inputIndex ) ;
312
279
const { script, isP2SH, isP2WSH, isSegwit } = getScriptFromInput (
313
280
inputIndex ,
@@ -316,13 +283,15 @@ class Psbt {
316
283
) ;
317
284
if ( ! script ) throw new Error ( `No script found for input #${ inputIndex } ` ) ;
318
285
checkPartialSigSighashes ( input ) ;
319
- const { finalScriptSig, finalScriptWitness } = finalScriptsFunc (
286
+ const fn = finalScriptsFunc || getFinalScripts ;
287
+ const { finalScriptSig, finalScriptWitness } = fn (
320
288
inputIndex ,
321
289
input ,
322
290
script ,
323
291
isSegwit ,
324
292
isP2SH ,
325
293
isP2WSH ,
294
+ this . __CACHE . __EC_LIB ,
326
295
) ;
327
296
if ( finalScriptSig ) this . data . updateInput ( inputIndex , { finalScriptSig } ) ;
328
297
if ( finalScriptWitness )
@@ -348,7 +317,10 @@ class Psbt {
348
317
redeemFromFinalWitnessScript ( input . finalScriptWitness ) ,
349
318
) ;
350
319
const type = result . type === 'raw' ? '' : result . type + '-' ;
351
- const mainType = classifyScript ( result . meaningfulScript ) ;
320
+ const mainType = classifyScript (
321
+ result . meaningfulScript ,
322
+ this . __CACHE . __EC_LIB ,
323
+ ) ;
352
324
return type + mainType ;
353
325
}
354
326
inputHasPubkey ( inputIndex , pubkey ) {
@@ -676,6 +648,41 @@ class Psbt {
676
648
}
677
649
}
678
650
exports . Psbt = Psbt ;
651
+ /**
652
+ * Helper method for converting a normal Signer into a Taproot Signer.
653
+ * Note that this helper method requires the Private Key of the Signer to be present.
654
+ * Steps:
655
+ * - if the Y coordinate of the Signer Public Key is odd then negate the Private Key
656
+ * - tweak the private key with the provided hash (should be empty for key-path spending)
657
+ * @param signer - a taproot signer object, the Private Key must be present
658
+ * @param opts - tweak options
659
+ * @returns a Signer having the Private and Public keys tweaked
660
+ */
661
+ function tweakSigner ( signer , opts ) {
662
+ // todo: test ecc??
663
+ let privateKey = signer . privateKey ;
664
+ if ( ! privateKey ) {
665
+ throw new Error ( 'Private key is required for tweaking signer!' ) ;
666
+ }
667
+ if ( signer . publicKey [ 0 ] === 3 ) {
668
+ privateKey = opts . eccLib . privateNegate ( privateKey ) ;
669
+ }
670
+ const tweakedPrivateKey = opts . eccLib . privateAdd (
671
+ privateKey ,
672
+ ( 0 , taprootutils_1 . tapTweakHash ) (
673
+ signer . publicKey . slice ( 1 , 33 ) ,
674
+ opts . tweakHash ,
675
+ ) ,
676
+ ) ;
677
+ if ( ! tweakedPrivateKey ) {
678
+ throw new Error ( 'Invalid tweaked private key!' ) ;
679
+ }
680
+ const ECPair = ( 0 , ecpair_1 . ECPairFactory ) ( opts . eccLib ) ;
681
+ return ECPair . fromPrivateKey ( Buffer . from ( tweakedPrivateKey ) , {
682
+ network : opts . network ,
683
+ } ) ;
684
+ }
685
+ exports . tweakSigner = tweakSigner ;
679
686
/**
680
687
* This function is needed to pass to the bip174 base class's fromBuffer.
681
688
* It takes the "transaction buffer" portion of the psbt buffer and returns a
@@ -928,8 +935,16 @@ function getTxCacheValue(key, name, inputs, c) {
928
935
if ( key === '__FEE_RATE' ) return c . __FEE_RATE ;
929
936
else if ( key === '__FEE' ) return c . __FEE ;
930
937
}
931
- function getFinalScripts ( inputIndex , input , script , isSegwit , isP2SH , isP2WSH ) {
932
- const scriptType = classifyScript ( script ) ;
938
+ function getFinalScripts (
939
+ inputIndex ,
940
+ input ,
941
+ script ,
942
+ isSegwit ,
943
+ isP2SH ,
944
+ isP2WSH ,
945
+ eccLib ,
946
+ ) {
947
+ const scriptType = classifyScript ( script , eccLib ) ;
933
948
if ( ! canFinalize ( input , script , scriptType ) )
934
949
throw new Error ( `Can not finalize input #${ inputIndex } ` ) ;
935
950
return prepareFinalScripts (
@@ -1063,7 +1078,7 @@ function getHashForSig(
1063
1078
prevout . value ,
1064
1079
sighashType ,
1065
1080
) ;
1066
- } else if ( isP2TR ( meaningfulScript , ecc ) ) {
1081
+ } else if ( isP2TR ( meaningfulScript , cache . __EC_LIB ) ) {
1067
1082
const prevOuts = inputs . map ( ( i , index ) =>
1068
1083
getScriptAndAmountFromUtxo ( index , i , cache ) ,
1069
1084
) ;
@@ -1143,7 +1158,7 @@ function getPayment(script, scriptType, partialSig) {
1143
1158
output : script ,
1144
1159
signature : partialSig [ 0 ] . signature ,
1145
1160
} ,
1146
- { eccLib : ecc } ,
1161
+ { validate : false } ,
1147
1162
) ;
1148
1163
break ;
1149
1164
}
@@ -1190,7 +1205,11 @@ function getScriptFromInput(inputIndex, input, cache) {
1190
1205
res . script = input . witnessUtxo . script ;
1191
1206
}
1192
1207
}
1193
- if ( input . witnessScript || isP2WPKH ( res . script ) || isP2TR ( res . script , ecc ) ) {
1208
+ if (
1209
+ input . witnessScript ||
1210
+ isP2WPKH ( res . script ) ||
1211
+ isP2TR ( res . script , cache . __EC_LIB )
1212
+ ) {
1194
1213
res . isSegwit = true ;
1195
1214
}
1196
1215
return res ;
@@ -1504,12 +1523,12 @@ function pubkeyInScript(pubkey, script) {
1504
1523
) ;
1505
1524
} ) ;
1506
1525
}
1507
- function classifyScript ( script ) {
1526
+ function classifyScript ( script , eccLib ) {
1508
1527
if ( isP2WPKH ( script ) ) return 'witnesspubkeyhash' ;
1509
1528
if ( isP2PKH ( script ) ) return 'pubkeyhash' ;
1510
1529
if ( isP2MS ( script ) ) return 'multisig' ;
1511
1530
if ( isP2PK ( script ) ) return 'pubkey' ;
1512
- if ( isP2TR ( script , ecc ) ) return 'taproot' ;
1531
+ if ( isP2TR ( script , eccLib ) ) return 'taproot' ;
1513
1532
return 'nonstandard' ;
1514
1533
}
1515
1534
function range ( n ) {
0 commit comments