Skip to content

Commit

Permalink
docs: remove PSBT duplicate annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
yihanga committed Jul 30, 2024
1 parent 39c5b82 commit 7dc2d80
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 15 deletions.
49 changes: 49 additions & 0 deletions src/psbt/bip371.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
/// <reference types="node" />
import { Taptree } from '../types';
import { PsbtInput, PsbtOutput, TapLeaf } from 'bip174/src/lib/interfaces';
/**
* Converts a public key to an X-only public key.
* @param pubKey The public key to convert.
* @returns The X-only public key.
*/
export declare const toXOnly: (pubKey: Buffer) => Buffer;
/**
* Default tapscript finalizer. It searches for the `tapLeafHashToFinalize` if provided.
Expand All @@ -14,11 +19,49 @@ export declare const toXOnly: (pubKey: Buffer) => Buffer;
export declare function tapScriptFinalizer(inputIndex: number, input: PsbtInput, tapLeafHashToFinalize?: Buffer): {
finalScriptWitness: Buffer | undefined;
};
/**
* Serializes a taproot signature.
* @param sig The signature to serialize.
* @param sighashType The sighash type. Optional.
* @returns The serialized taproot signature.
*/
export declare function serializeTaprootSignature(sig: Buffer, sighashType?: number): Buffer;
/**
* Checks if a PSBT input is a taproot input.
* @param input The PSBT input to check.
* @returns True if the input is a taproot input, false otherwise.
*/
export declare function isTaprootInput(input: PsbtInput): boolean;
/**
* Checks if a PSBT output is a taproot output.
* @param output The PSBT output to check.
* @param script The script to check. Optional.
* @returns True if the output is a taproot output, false otherwise.
*/
export declare function isTaprootOutput(output: PsbtOutput, script?: Buffer): boolean;
/**
* Checks the taproot input fields for consistency.
* @param inputData The original input data.
* @param newInputData The new input data.
* @param action The action being performed.
* @throws Throws an error if the input fields are inconsistent.
*/
export declare function checkTaprootInputFields(inputData: PsbtInput, newInputData: PsbtInput, action: string): void;
/**
* Checks the taproot output fields for consistency.
* @param outputData The original output data.
* @param newOutputData The new output data.
* @param action The action being performed.
* @throws Throws an error if the output fields are inconsistent.
*/
export declare function checkTaprootOutputFields(outputData: PsbtOutput, newOutputData: PsbtOutput, action: string): void;
/**
* Tweak the internal public key for a specific input.
* @param inputIndex - The index of the input.
* @param input - The PsbtInput object representing the input.
* @returns The tweaked internal public key.
* @throws Error if the tap internal key cannot be tweaked.
*/
export declare function tweakInternalPubKey(inputIndex: number, input: PsbtInput): Buffer;
/**
* Convert a binary tree to a BIP371 type list. Each element of the list is (according to BIP371):
Expand All @@ -38,4 +81,10 @@ export declare function tapTreeToList(tree: Taptree): TapLeaf[];
* @returns the corresponding taptree, or throws an exception if the tree cannot be reconstructed
*/
export declare function tapTreeFromList(leaves?: TapLeaf[]): Taptree;
/**
* Checks the taproot input for signatures.
* @param input The PSBT input to check.
* @param action The action being performed.
* @returns True if the input has taproot signatures, false otherwise.
*/
export declare function checkTaprootInputForSigs(input: PsbtInput, action: string): boolean;
106 changes: 106 additions & 0 deletions src/psbt/bip371.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ const psbtutils_1 = require('./psbtutils');
const bip341_1 = require('../payments/bip341');
const payments_1 = require('../payments');
const psbtutils_2 = require('./psbtutils');
/**
* Converts a public key to an X-only public key.
* @param pubKey The public key to convert.
* @returns The X-only public key.
*/
const toXOnly = pubKey => (pubKey.length === 32 ? pubKey : pubKey.slice(1, 33));
exports.toXOnly = toXOnly;
/**
Expand Down Expand Up @@ -46,13 +51,24 @@ function tapScriptFinalizer(inputIndex, input, tapLeafHashToFinalize) {
}
}
exports.tapScriptFinalizer = tapScriptFinalizer;
/**
* Serializes a taproot signature.
* @param sig The signature to serialize.
* @param sighashType The sighash type. Optional.
* @returns The serialized taproot signature.
*/
function serializeTaprootSignature(sig, sighashType) {
const sighashTypeByte = sighashType
? Buffer.from([sighashType])
: Buffer.from([]);
return Buffer.concat([sig, sighashTypeByte]);
}
exports.serializeTaprootSignature = serializeTaprootSignature;
/**
* Checks if a PSBT input is a taproot input.
* @param input The PSBT input to check.
* @returns True if the input is a taproot input, false otherwise.
*/
function isTaprootInput(input) {
return (
input &&
Expand All @@ -66,6 +82,12 @@ function isTaprootInput(input) {
);
}
exports.isTaprootInput = isTaprootInput;
/**
* Checks if a PSBT output is a taproot output.
* @param output The PSBT output to check.
* @param script The script to check. Optional.
* @returns True if the output is a taproot output, false otherwise.
*/
function isTaprootOutput(output, script) {
return (
output &&
Expand All @@ -78,11 +100,25 @@ function isTaprootOutput(output, script) {
);
}
exports.isTaprootOutput = isTaprootOutput;
/**
* Checks the taproot input fields for consistency.
* @param inputData The original input data.
* @param newInputData The new input data.
* @param action The action being performed.
* @throws Throws an error if the input fields are inconsistent.
*/
function checkTaprootInputFields(inputData, newInputData, action) {
checkMixedTaprootAndNonTaprootInputFields(inputData, newInputData, action);
checkIfTapLeafInTree(inputData, newInputData, action);
}
exports.checkTaprootInputFields = checkTaprootInputFields;
/**
* Checks the taproot output fields for consistency.
* @param outputData The original output data.
* @param newOutputData The new output data.
* @param action The action being performed.
* @throws Throws an error if the output fields are inconsistent.
*/
function checkTaprootOutputFields(outputData, newOutputData, action) {
checkMixedTaprootAndNonTaprootOutputFields(outputData, newOutputData, action);
checkTaprootScriptPubkey(outputData, newOutputData);
Expand All @@ -100,6 +136,13 @@ function checkTaprootScriptPubkey(outputData, newOutputData) {
throw new Error('Error adding output. Script or address mismatch.');
}
}
/**
* Returns the Taproot script public key.
*
* @param tapInternalKey - The Taproot internal key.
* @param tapTree - The Taproot tree (optional).
* @returns The Taproot script public key.
*/
function getTaprootScripPubkey(tapInternalKey, tapTree) {
const scriptTree = tapTree && tapTreeFromList(tapTree.leaves);
const { output } = (0, payments_1.p2tr)({
Expand All @@ -108,6 +151,13 @@ function getTaprootScripPubkey(tapInternalKey, tapTree) {
});
return output;
}
/**
* Tweak the internal public key for a specific input.
* @param inputIndex - The index of the input.
* @param input - The PsbtInput object representing the input.
* @returns The tweaked internal public key.
* @throws Error if the tap internal key cannot be tweaked.
*/
function tweakInternalPubKey(inputIndex, input) {
const tapInternalKey = input.tapInternalKey;
const outputKey =
Expand Down Expand Up @@ -155,20 +205,36 @@ function tapTreeFromList(leaves = []) {
return instertLeavesInTree(leaves);
}
exports.tapTreeFromList = tapTreeFromList;
/**
* Checks the taproot input for signatures.
* @param input The PSBT input to check.
* @param action The action being performed.
* @returns True if the input has taproot signatures, false otherwise.
*/
function checkTaprootInputForSigs(input, action) {
const sigs = extractTaprootSigs(input);
return sigs.some(sig =>
(0, psbtutils_2.signatureBlocksAction)(sig, decodeSchnorrSignature, action),
);
}
exports.checkTaprootInputForSigs = checkTaprootInputForSigs;
/**
* Decodes a Schnorr signature.
* @param signature The signature to decode.
* @returns The decoded Schnorr signature.
*/
function decodeSchnorrSignature(signature) {
return {
signature: signature.slice(0, 64),
hashType:
signature.slice(64)[0] || transaction_1.Transaction.SIGHASH_DEFAULT,
};
}
/**
* Extracts taproot signatures from a PSBT input.
* @param input The PSBT input to extract signatures from.
* @returns An array of taproot signatures.
*/
function extractTaprootSigs(input) {
const sigs = [];
if (input.tapKeySig) sigs.push(input.tapKeySig);
Expand All @@ -180,12 +246,25 @@ function extractTaprootSigs(input) {
}
return sigs;
}
/**
* Gets the taproot signature from the witness.
* @param finalScriptWitness The final script witness.
* @returns The taproot signature, or undefined if not found.
*/
function getTapKeySigFromWithness(finalScriptWitness) {
if (!finalScriptWitness) return;
const witness = finalScriptWitness.slice(2);
// todo: add schnorr signature validation
if (witness.length === 64 || witness.length === 65) return witness;
}
/**
* Converts a binary tree to a BIP371 type list.
* @param tree The binary tap tree.
* @param leaves A list of tapleaves. Optional.
* @param depth The current depth. Optional.
* @returns A list of BIP 371 tapleaves.
* @throws Throws an error if the taptree cannot be converted to a tapleaf list.
*/
function _tapTreeToList(tree, leaves = [], depth = 0) {
if (depth > bip341_1.MAX_TAPTREE_DEPTH)
throw new Error('Max taptree depth exceeded.');
Expand All @@ -202,6 +281,12 @@ function _tapTreeToList(tree, leaves = [], depth = 0) {
if (tree[1]) _tapTreeToList(tree[1], leaves, depth + 1);
return leaves;
}
/**
* Inserts the tapleaves into the taproot tree.
* @param leaves The tapleaves to insert.
* @returns The taproot tree.
* @throws Throws an error if there is no room left to insert a tapleaf in the tree.
*/
function instertLeavesInTree(leaves) {
let tree;
for (const leaf of leaves) {
Expand All @@ -210,6 +295,13 @@ function instertLeavesInTree(leaves) {
}
return tree;
}
/**
* Inserts a tapleaf into the taproot tree.
* @param leaf The tapleaf to insert.
* @param tree The taproot tree.
* @param depth The current depth. Optional.
* @returns The updated taproot tree.
*/
function instertLeafInTree(leaf, tree, depth = 0) {
if (depth > bip341_1.MAX_TAPTREE_DEPTH)
throw new Error('Max taptree depth exceeded.');
Expand All @@ -227,6 +319,13 @@ function instertLeafInTree(leaf, tree, depth = 0) {
const rightSide = instertLeafInTree(leaf, tree && tree[1], depth + 1);
if (rightSide) return [tree && tree[0], rightSide];
}
/**
* Checks the input fields for mixed taproot and non-taproot fields.
* @param inputData The original input data.
* @param newInputData The new input data.
* @param action The action being performed.
* @throws Throws an error if the input fields are inconsistent.
*/
function checkMixedTaprootAndNonTaprootInputFields(
inputData,
newInputData,
Expand All @@ -246,6 +345,13 @@ function checkMixedTaprootAndNonTaprootInputFields(
`Cannot use both taproot and non-taproot fields.`,
);
}
/**
* Checks the output fields for mixed taproot and non-taproot fields.
* @param inputData The original output data.
* @param newInputData The new output data.
* @param action The action being performed.
* @throws Throws an error if the output fields are inconsistent.
*/
function checkMixedTaprootAndNonTaprootOutputFields(
inputData,
newInputData,
Expand Down
5 changes: 0 additions & 5 deletions src/psbt/psbtutils.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ export declare const isP2TR: (script: Buffer) => boolean;
* @param witness The witness stack to convert.
* @returns The script witness as a Buffer.
*/
/**
* Converts a witness stack to a script witness.
* @param witness The witness stack to convert.
* @returns The converted script witness.
*/
export declare function witnessStackToScriptWitness(witness: Buffer[]): Buffer;
/**
* Finds the position of a public key in a script.
Expand Down
10 changes: 5 additions & 5 deletions src/psbt/psbtutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ const bscript = require('../script');
const transaction_1 = require('../transaction');
const crypto_1 = require('../crypto');
const payments = require('../payments');
/**
* Checks if a given payment factory can generate a payment script from a given script.
* @param payment The payment factory to check.
* @returns A function that takes a script and returns a boolean indicating whether the payment factory can generate a payment script from the script.
*/
function isPaymentFactory(payment) {
return script => {
try {
Expand All @@ -40,11 +45,6 @@ exports.isP2TR = isPaymentFactory(payments.p2tr);
* @param witness The witness stack to convert.
* @returns The script witness as a Buffer.
*/
/**
* Converts a witness stack to a script witness.
* @param witness The witness stack to convert.
* @returns The converted script witness.
*/
function witnessStackToScriptWitness(witness) {
let buffer = Buffer.allocUnsafe(0);
function writeSlice(slice) {
Expand Down
12 changes: 7 additions & 5 deletions ts_src/psbt/psbtutils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import { Transaction } from '../transaction';
import { hash160 } from '../crypto';
import * as payments from '../payments';

/**
* Checks if a given payment factory can generate a payment script from a given script.
* @param payment The payment factory to check.
* @returns A function that takes a script and returns a boolean indicating whether the payment factory can generate a payment script from the script.
*/
function isPaymentFactory(payment: any): (script: Buffer) => boolean {
return (script: Buffer): boolean => {
try {
Expand All @@ -15,6 +20,7 @@ function isPaymentFactory(payment: any): (script: Buffer) => boolean {
}
};
}

export const isP2MS = isPaymentFactory(payments.p2ms);
export const isP2PK = isPaymentFactory(payments.p2pk);
export const isP2PKH = isPaymentFactory(payments.p2pkh);
Expand All @@ -28,11 +34,6 @@ export const isP2TR = isPaymentFactory(payments.p2tr);
* @param witness The witness stack to convert.
* @returns The script witness as a Buffer.
*/
/**
* Converts a witness stack to a script witness.
* @param witness The witness stack to convert.
* @returns The converted script witness.
*/
export function witnessStackToScriptWitness(witness: Buffer[]): Buffer {
let buffer = Buffer.allocUnsafe(0);

Expand Down Expand Up @@ -114,6 +115,7 @@ type SignatureDecodeFunc = (buffer: Buffer) => {
signature: Buffer;
hashType: number;
};

/**
* Determines if a given action is allowed for a signature block.
* @param signature - The signature block.
Expand Down

0 comments on commit 7dc2d80

Please sign in to comment.