@@ -18,6 +18,11 @@ const psbtutils_1 = require('./psbtutils');
1818const bip341_1 = require ( '../payments/bip341' ) ;
1919const payments_1 = require ( '../payments' ) ;
2020const psbtutils_2 = require ( './psbtutils' ) ;
21+ /**
22+ * Converts a public key to an X-only public key.
23+ * @param pubKey The public key to convert.
24+ * @returns The X-only public key.
25+ */
2126const toXOnly = pubKey => ( pubKey . length === 32 ? pubKey : pubKey . slice ( 1 , 33 ) ) ;
2227exports . toXOnly = toXOnly ;
2328/**
@@ -46,13 +51,24 @@ function tapScriptFinalizer(inputIndex, input, tapLeafHashToFinalize) {
4651 }
4752}
4853exports . tapScriptFinalizer = tapScriptFinalizer ;
54+ /**
55+ * Serializes a taproot signature.
56+ * @param sig The signature to serialize.
57+ * @param sighashType The sighash type. Optional.
58+ * @returns The serialized taproot signature.
59+ */
4960function serializeTaprootSignature ( sig , sighashType ) {
5061 const sighashTypeByte = sighashType
5162 ? Buffer . from ( [ sighashType ] )
5263 : Buffer . from ( [ ] ) ;
5364 return Buffer . concat ( [ sig , sighashTypeByte ] ) ;
5465}
5566exports . serializeTaprootSignature = serializeTaprootSignature ;
67+ /**
68+ * Checks if a PSBT input is a taproot input.
69+ * @param input The PSBT input to check.
70+ * @returns True if the input is a taproot input, false otherwise.
71+ */
5672function isTaprootInput ( input ) {
5773 return (
5874 input &&
@@ -66,6 +82,12 @@ function isTaprootInput(input) {
6682 ) ;
6783}
6884exports . isTaprootInput = isTaprootInput ;
85+ /**
86+ * Checks if a PSBT output is a taproot output.
87+ * @param output The PSBT output to check.
88+ * @param script The script to check. Optional.
89+ * @returns True if the output is a taproot output, false otherwise.
90+ */
6991function isTaprootOutput ( output , script ) {
7092 return (
7193 output &&
@@ -78,11 +100,25 @@ function isTaprootOutput(output, script) {
78100 ) ;
79101}
80102exports . isTaprootOutput = isTaprootOutput ;
103+ /**
104+ * Checks the taproot input fields for consistency.
105+ * @param inputData The original input data.
106+ * @param newInputData The new input data.
107+ * @param action The action being performed.
108+ * @throws Throws an error if the input fields are inconsistent.
109+ */
81110function checkTaprootInputFields ( inputData , newInputData , action ) {
82111 checkMixedTaprootAndNonTaprootInputFields ( inputData , newInputData , action ) ;
83112 checkIfTapLeafInTree ( inputData , newInputData , action ) ;
84113}
85114exports . checkTaprootInputFields = checkTaprootInputFields ;
115+ /**
116+ * Checks the taproot output fields for consistency.
117+ * @param outputData The original output data.
118+ * @param newOutputData The new output data.
119+ * @param action The action being performed.
120+ * @throws Throws an error if the output fields are inconsistent.
121+ */
86122function checkTaprootOutputFields ( outputData , newOutputData , action ) {
87123 checkMixedTaprootAndNonTaprootOutputFields ( outputData , newOutputData , action ) ;
88124 checkTaprootScriptPubkey ( outputData , newOutputData ) ;
@@ -100,6 +136,13 @@ function checkTaprootScriptPubkey(outputData, newOutputData) {
100136 throw new Error ( 'Error adding output. Script or address mismatch.' ) ;
101137 }
102138}
139+ /**
140+ * Returns the Taproot script public key.
141+ *
142+ * @param tapInternalKey - The Taproot internal key.
143+ * @param tapTree - The Taproot tree (optional).
144+ * @returns The Taproot script public key.
145+ */
103146function getTaprootScripPubkey ( tapInternalKey , tapTree ) {
104147 const scriptTree = tapTree && tapTreeFromList ( tapTree . leaves ) ;
105148 const { output } = ( 0 , payments_1 . p2tr ) ( {
@@ -108,6 +151,13 @@ function getTaprootScripPubkey(tapInternalKey, tapTree) {
108151 } ) ;
109152 return output ;
110153}
154+ /**
155+ * Tweak the internal public key for a specific input.
156+ * @param inputIndex - The index of the input.
157+ * @param input - The PsbtInput object representing the input.
158+ * @returns The tweaked internal public key.
159+ * @throws Error if the tap internal key cannot be tweaked.
160+ */
111161function tweakInternalPubKey ( inputIndex , input ) {
112162 const tapInternalKey = input . tapInternalKey ;
113163 const outputKey =
@@ -155,20 +205,36 @@ function tapTreeFromList(leaves = []) {
155205 return instertLeavesInTree ( leaves ) ;
156206}
157207exports . tapTreeFromList = tapTreeFromList ;
208+ /**
209+ * Checks the taproot input for signatures.
210+ * @param input The PSBT input to check.
211+ * @param action The action being performed.
212+ * @returns True if the input has taproot signatures, false otherwise.
213+ */
158214function checkTaprootInputForSigs ( input , action ) {
159215 const sigs = extractTaprootSigs ( input ) ;
160216 return sigs . some ( sig =>
161217 ( 0 , psbtutils_2 . signatureBlocksAction ) ( sig , decodeSchnorrSignature , action ) ,
162218 ) ;
163219}
164220exports . checkTaprootInputForSigs = checkTaprootInputForSigs ;
221+ /**
222+ * Decodes a Schnorr signature.
223+ * @param signature The signature to decode.
224+ * @returns The decoded Schnorr signature.
225+ */
165226function decodeSchnorrSignature ( signature ) {
166227 return {
167228 signature : signature . slice ( 0 , 64 ) ,
168229 hashType :
169230 signature . slice ( 64 ) [ 0 ] || transaction_1 . Transaction . SIGHASH_DEFAULT ,
170231 } ;
171232}
233+ /**
234+ * Extracts taproot signatures from a PSBT input.
235+ * @param input The PSBT input to extract signatures from.
236+ * @returns An array of taproot signatures.
237+ */
172238function extractTaprootSigs ( input ) {
173239 const sigs = [ ] ;
174240 if ( input . tapKeySig ) sigs . push ( input . tapKeySig ) ;
@@ -180,12 +246,25 @@ function extractTaprootSigs(input) {
180246 }
181247 return sigs ;
182248}
249+ /**
250+ * Gets the taproot signature from the witness.
251+ * @param finalScriptWitness The final script witness.
252+ * @returns The taproot signature, or undefined if not found.
253+ */
183254function getTapKeySigFromWithness ( finalScriptWitness ) {
184255 if ( ! finalScriptWitness ) return ;
185256 const witness = finalScriptWitness . slice ( 2 ) ;
186257 // todo: add schnorr signature validation
187258 if ( witness . length === 64 || witness . length === 65 ) return witness ;
188259}
260+ /**
261+ * Converts a binary tree to a BIP371 type list.
262+ * @param tree The binary tap tree.
263+ * @param leaves A list of tapleaves. Optional.
264+ * @param depth The current depth. Optional.
265+ * @returns A list of BIP 371 tapleaves.
266+ * @throws Throws an error if the taptree cannot be converted to a tapleaf list.
267+ */
189268function _tapTreeToList ( tree , leaves = [ ] , depth = 0 ) {
190269 if ( depth > bip341_1 . MAX_TAPTREE_DEPTH )
191270 throw new Error ( 'Max taptree depth exceeded.' ) ;
@@ -202,6 +281,12 @@ function _tapTreeToList(tree, leaves = [], depth = 0) {
202281 if ( tree [ 1 ] ) _tapTreeToList ( tree [ 1 ] , leaves , depth + 1 ) ;
203282 return leaves ;
204283}
284+ /**
285+ * Inserts the tapleaves into the taproot tree.
286+ * @param leaves The tapleaves to insert.
287+ * @returns The taproot tree.
288+ * @throws Throws an error if there is no room left to insert a tapleaf in the tree.
289+ */
205290function instertLeavesInTree ( leaves ) {
206291 let tree ;
207292 for ( const leaf of leaves ) {
@@ -210,6 +295,13 @@ function instertLeavesInTree(leaves) {
210295 }
211296 return tree ;
212297}
298+ /**
299+ * Inserts a tapleaf into the taproot tree.
300+ * @param leaf The tapleaf to insert.
301+ * @param tree The taproot tree.
302+ * @param depth The current depth. Optional.
303+ * @returns The updated taproot tree.
304+ */
213305function instertLeafInTree ( leaf , tree , depth = 0 ) {
214306 if ( depth > bip341_1 . MAX_TAPTREE_DEPTH )
215307 throw new Error ( 'Max taptree depth exceeded.' ) ;
@@ -227,6 +319,13 @@ function instertLeafInTree(leaf, tree, depth = 0) {
227319 const rightSide = instertLeafInTree ( leaf , tree && tree [ 1 ] , depth + 1 ) ;
228320 if ( rightSide ) return [ tree && tree [ 0 ] , rightSide ] ;
229321}
322+ /**
323+ * Checks the input fields for mixed taproot and non-taproot fields.
324+ * @param inputData The original input data.
325+ * @param newInputData The new input data.
326+ * @param action The action being performed.
327+ * @throws Throws an error if the input fields are inconsistent.
328+ */
230329function checkMixedTaprootAndNonTaprootInputFields (
231330 inputData ,
232331 newInputData ,
@@ -246,6 +345,13 @@ function checkMixedTaprootAndNonTaprootInputFields(
246345 `Cannot use both taproot and non-taproot fields.` ,
247346 ) ;
248347}
348+ /**
349+ * Checks the output fields for mixed taproot and non-taproot fields.
350+ * @param inputData The original output data.
351+ * @param newInputData The new output data.
352+ * @param action The action being performed.
353+ * @throws Throws an error if the output fields are inconsistent.
354+ */
249355function checkMixedTaprootAndNonTaprootOutputFields (
250356 inputData ,
251357 newInputData ,
0 commit comments