From 833e031a5368aca65717af34fc228b8ddba1cf40 Mon Sep 17 00:00:00 2001
From: jasonandjay <342690199@qq.com>
Date: Fri, 12 Apr 2024 13:20:55 +0800
Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=85=20perfs:=20Simplify=20psbt=20util?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/psbt/bip371.js | 4 +-
src/psbt/global/cache.d.ts | 6 +-
src/psbt/global/index.js | 10 +---
src/psbt/global/sign.d.ts | 18 +++++-
src/psbt/global/sign.js | 89 +++++++++++++++++++++++++++++-
src/psbt/input/index.js | 4 +-
src/psbt/input/script.d.ts | 4 +-
src/psbt/interfaces.d.ts | 4 ++
src/psbt/psbtutils.d.ts | 20 -------
src/psbt/psbtutils.js | 87 -----------------------------
ts_src/psbt/bip371.ts | 7 ++-
ts_src/psbt/global/cache.ts | 14 ++---
ts_src/psbt/global/hash.ts | 2 +-
ts_src/psbt/global/index.ts | 14 +----
ts_src/psbt/global/sign.ts | 95 +++++++++++++++++++++++++++++++-
ts_src/psbt/input/index.ts | 2 +-
ts_src/psbt/input/script.ts | 29 +++++-----
ts_src/psbt/interfaces.ts | 19 ++++---
ts_src/psbt/psbtutils.ts | 107 ++++--------------------------------
19 files changed, 264 insertions(+), 271 deletions(-)
diff --git a/src/psbt/bip371.js b/src/psbt/bip371.js
index 93fe10659..7cd682427 100644
--- a/src/psbt/bip371.js
+++ b/src/psbt/bip371.js
@@ -16,8 +16,8 @@ const types_1 = require('../types');
const transaction_1 = require('../transaction');
const bip341_1 = require('../payments/bip341');
const payments_1 = require('../payments');
-const psbtutils_1 = require('./psbtutils');
const script_1 = require('./input/script');
+const sign_1 = require('./global/sign');
const toXOnly = pubKey => (pubKey.length === 32 ? pubKey : pubKey.slice(1, 33));
exports.toXOnly = toXOnly;
/**
@@ -158,7 +158,7 @@ exports.tapTreeFromList = tapTreeFromList;
function checkTaprootInputForSigs(input, action) {
const sigs = extractTaprootSigs(input);
return sigs.some(sig =>
- (0, psbtutils_1.signatureBlocksAction)(sig, decodeSchnorrSignature, action),
+ (0, sign_1.signatureBlocksAction)(sig, decodeSchnorrSignature, action),
);
}
exports.checkTaprootInputForSigs = checkTaprootInputForSigs;
diff --git a/src/psbt/global/cache.d.ts b/src/psbt/global/cache.d.ts
index fdb9fd161..2a9efaea3 100644
--- a/src/psbt/global/cache.d.ts
+++ b/src/psbt/global/cache.d.ts
@@ -1,7 +1,7 @@
///
-import { PsbtInput } from "bip174/src/lib/interfaces";
-import { PsbtCache, TxCacheNumberKey } from "../interfaces";
-import { Transaction } from "../../transaction";
+import { PsbtInput } from 'bip174/src/lib/interfaces';
+import { PsbtCache, TxCacheNumberKey } from '../interfaces';
+import { Transaction } from '../../transaction';
export declare function checkCache(cache: PsbtCache): void;
export declare function checkTxInputCache(cache: PsbtCache, input: {
hash: Buffer;
diff --git a/src/psbt/global/index.js b/src/psbt/global/index.js
index 9d7943108..9f5659a73 100644
--- a/src/psbt/global/index.js
+++ b/src/psbt/global/index.js
@@ -8,9 +8,8 @@ exports.isFinalized =
const sign_1 = require('./sign');
const payments = require('../../payments');
const script_1 = require('../input/script');
-const { isP2MS, isP2PK, isP2PKH, isP2WPKH } = payments;
function getFinalScripts(inputIndex, input, script, isSegwit, isP2SH, isP2WSH) {
- const scriptType = classifyScript(script);
+ const scriptType = (0, script_1.classifyScript)(script);
if (!canFinalize(input, script, scriptType))
throw new Error(`Can not finalize input #${inputIndex}`);
return prepareFinalScripts(
@@ -119,13 +118,6 @@ function getSortedSigs(script, partialSig) {
})
.filter(v => !!v);
}
-function classifyScript(script) {
- if (isP2WPKH(script)) return 'witnesspubkeyhash';
- if (isP2PKH(script)) return 'pubkeyhash';
- if (isP2MS(script)) return 'multisig';
- if (isP2PK(script)) return 'pubkey';
- return 'nonstandard';
-}
function canFinalize(input, script, scriptType) {
switch (scriptType) {
case 'pubkey':
diff --git a/src/psbt/global/sign.d.ts b/src/psbt/global/sign.d.ts
index 7ee39ab13..1595118a1 100644
--- a/src/psbt/global/sign.d.ts
+++ b/src/psbt/global/sign.d.ts
@@ -1,6 +1,22 @@
///
-import { PsbtInput } from "bip174/src/lib/interfaces";
+import { PsbtInput } from 'bip174/src/lib/interfaces';
+import { SignatureDecodeFunc } from '../interfaces';
export declare function hasSigs(neededSigs: number, partialSig?: any[], pubkeys?: Buffer[]): boolean;
export declare function checkPartialSigSighashes(input: PsbtInput): void;
export declare function trimTaprootSig(signature: Buffer): Buffer;
export declare function isSigLike(buf: Buffer): boolean;
+/**
+ * Checks if an input contains a signature for a specific action.
+ * @param input - The input to check.
+ * @param action - The action to check for.
+ * @returns A boolean indicating whether the input contains a signature for the specified action.
+ */
+export declare function checkInputForSig(input: PsbtInput, action: string): boolean;
+/**
+ * Determines if a given action is allowed for a signature block.
+ * @param signature - The signature block.
+ * @param signatureDecodeFn - The function used to decode the signature.
+ * @param action - The action to be checked.
+ * @returns True if the action is allowed, false otherwise.
+ */
+export declare function signatureBlocksAction(signature: Buffer, signatureDecodeFn: SignatureDecodeFunc, action: string): boolean;
diff --git a/src/psbt/global/sign.js b/src/psbt/global/sign.js
index f4e675e31..bb86f9545 100644
--- a/src/psbt/global/sign.js
+++ b/src/psbt/global/sign.js
@@ -1,11 +1,14 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
-exports.isSigLike =
+exports.signatureBlocksAction =
+ exports.checkInputForSig =
+ exports.isSigLike =
exports.trimTaprootSig =
exports.checkPartialSigSighashes =
exports.hasSigs =
void 0;
const script = require('../../script');
+const transaction_1 = require('../../transaction');
function hasSigs(neededSigs, partialSig, pubkeys) {
if (!partialSig) return false;
let sigs;
@@ -42,6 +45,90 @@ function isSigLike(buf) {
return script.isCanonicalScriptSignature(buf);
}
exports.isSigLike = isSigLike;
+/**
+ * Checks if an input contains a signature for a specific action.
+ * @param input - The input to check.
+ * @param action - The action to check for.
+ * @returns A boolean indicating whether the input contains a signature for the specified action.
+ */
+function checkInputForSig(input, action) {
+ const pSigs = extractPartialSigs(input);
+ return pSigs.some(pSig =>
+ signatureBlocksAction(pSig, script.signature.decode, action),
+ );
+}
+exports.checkInputForSig = checkInputForSig;
+/**
+ * Determines if a given action is allowed for a signature block.
+ * @param signature - The signature block.
+ * @param signatureDecodeFn - The function used to decode the signature.
+ * @param action - The action to be checked.
+ * @returns True if the action is allowed, false otherwise.
+ */
+function signatureBlocksAction(signature, signatureDecodeFn, action) {
+ const { hashType } = signatureDecodeFn(signature);
+ const whitelist = [];
+ const isAnyoneCanPay =
+ hashType & transaction_1.Transaction.SIGHASH_ANYONECANPAY;
+ if (isAnyoneCanPay) whitelist.push('addInput');
+ const hashMod = hashType & 0x1f;
+ switch (hashMod) {
+ case transaction_1.Transaction.SIGHASH_ALL:
+ break;
+ case transaction_1.Transaction.SIGHASH_SINGLE:
+ case transaction_1.Transaction.SIGHASH_NONE:
+ whitelist.push('addOutput');
+ whitelist.push('setInputSequence');
+ break;
+ }
+ if (whitelist.indexOf(action) === -1) {
+ return true;
+ }
+ return false;
+}
+exports.signatureBlocksAction = signatureBlocksAction;
+/**
+ * Extracts the signatures from a PsbtInput object.
+ * If the input has partial signatures, it returns an array of the signatures.
+ * If the input does not have partial signatures, it checks if it has a finalScriptSig or finalScriptWitness.
+ * If it does, it extracts the signatures from the final scripts and returns them.
+ * If none of the above conditions are met, it returns an empty array.
+ *
+ * @param input - The PsbtInput object from which to extract the signatures.
+ * @returns An array of signatures extracted from the PsbtInput object.
+ */
+function extractPartialSigs(input) {
+ let pSigs = [];
+ if ((input.partialSig || []).length === 0) {
+ if (!input.finalScriptSig && !input.finalScriptWitness) return [];
+ pSigs = getPsigsFromInputFinalScripts(input);
+ } else {
+ pSigs = input.partialSig;
+ }
+ return pSigs.map(p => p.signature);
+}
+/**
+ * Retrieves the partial signatures (Psigs) from the input's final scripts.
+ * Psigs are extracted from both the final scriptSig and final scriptWitness of the input.
+ * Only canonical script signatures are considered.
+ *
+ * @param input - The PsbtInput object representing the input.
+ * @returns An array of PartialSig objects containing the extracted Psigs.
+ */
+function getPsigsFromInputFinalScripts(input) {
+ const scriptItems = !input.finalScriptSig
+ ? []
+ : script.decompile(input.finalScriptSig) || [];
+ const witnessItems = !input.finalScriptWitness
+ ? []
+ : script.decompile(input.finalScriptWitness) || [];
+ return scriptItems
+ .concat(witnessItems)
+ .filter(item => {
+ return Buffer.isBuffer(item) && script.isCanonicalScriptSignature(item);
+ })
+ .map(sig => ({ signature: sig }));
+}
function compressPubkey(pubkey) {
if (pubkey.length === 65) {
const parity = pubkey[64] & 1;
diff --git a/src/psbt/input/index.js b/src/psbt/input/index.js
index f8af373ae..d9d697271 100644
--- a/src/psbt/input/index.js
+++ b/src/psbt/input/index.js
@@ -7,7 +7,7 @@ exports.pubkeyInInput =
exports.checkInputsForPartialSig =
void 0;
const bip371_1 = require('../bip371');
-const psbtutils_1 = require('../psbtutils');
+const sign_1 = require('../global/sign');
const cache_1 = require('../global/cache');
const script_1 = require('./script');
const payments_1 = require('../../payments');
@@ -15,7 +15,7 @@ function checkInputsForPartialSig(inputs, action) {
inputs.forEach(input => {
const throws = (0, bip371_1.isTaprootInput)(input)
? (0, bip371_1.checkTaprootInputForSigs)(input, action)
- : (0, psbtutils_1.checkInputForSig)(input, action);
+ : (0, sign_1.checkInputForSig)(input, action);
if (throws)
throw new Error('Can not modify transaction, signatures exist.');
});
diff --git a/src/psbt/input/script.d.ts b/src/psbt/input/script.d.ts
index 5cf2df16a..09fbf9a77 100644
--- a/src/psbt/input/script.d.ts
+++ b/src/psbt/input/script.d.ts
@@ -1,6 +1,6 @@
///
-import { PsbtInput } from "bip174/src/lib/interfaces";
-import { GetScriptReturn, PsbtCache, ScriptType } from "../interfaces";
+import { PsbtInput } from 'bip174/src/lib/interfaces';
+import { GetScriptReturn, PsbtCache, ScriptType } from '../interfaces';
export declare function getMeaningfulScript(script: Buffer, index: number, ioType: 'input' | 'output', redeemScript?: Buffer, witnessScript?: Buffer): {
meaningfulScript: Buffer;
type: 'p2sh' | 'p2wsh' | 'p2sh-p2wsh' | 'raw';
diff --git a/src/psbt/interfaces.d.ts b/src/psbt/interfaces.d.ts
index 7f5da5926..48d7daf21 100644
--- a/src/psbt/interfaces.d.ts
+++ b/src/psbt/interfaces.d.ts
@@ -121,4 +121,8 @@ tapLeafHashToFinalize?: Buffer) => {
export type ValidateSigFunction = (pubkey: Buffer, msghash: Buffer, signature: Buffer) => boolean;
export type AllScriptType = 'witnesspubkeyhash' | 'pubkeyhash' | 'multisig' | 'pubkey' | 'nonstandard' | 'p2sh-witnesspubkeyhash' | 'p2sh-pubkeyhash' | 'p2sh-multisig' | 'p2sh-pubkey' | 'p2sh-nonstandard' | 'p2wsh-pubkeyhash' | 'p2wsh-multisig' | 'p2wsh-pubkey' | 'p2wsh-nonstandard' | 'p2sh-p2wsh-pubkeyhash' | 'p2sh-p2wsh-multisig' | 'p2sh-p2wsh-pubkey' | 'p2sh-p2wsh-nonstandard';
export type ScriptType = 'witnesspubkeyhash' | 'pubkeyhash' | 'multisig' | 'pubkey' | 'nonstandard';
+export type SignatureDecodeFunc = (buffer: Buffer) => {
+ signature: Buffer;
+ hashType: number;
+};
export {};
diff --git a/src/psbt/psbtutils.d.ts b/src/psbt/psbtutils.d.ts
index 7b8c2a142..ed4717d3a 100644
--- a/src/psbt/psbtutils.d.ts
+++ b/src/psbt/psbtutils.d.ts
@@ -2,28 +2,8 @@
import { PsbtInput } from 'bip174/src/lib/interfaces';
import { HDSigner, HDSignerAsync, PsbtCache, PsbtOpts, Signer, SignerAsync } from './interfaces';
import { Psbt } from '../psbt';
-/**
- * Checks if an input contains a signature for a specific action.
- * @param input - The input to check.
- * @param action - The action to check for.
- * @returns A boolean indicating whether the input contains a signature for the specified action.
- */
-export declare function checkInputForSig(input: PsbtInput, action: string): boolean;
-type SignatureDecodeFunc = (buffer: Buffer) => {
- signature: Buffer;
- hashType: number;
-};
-/**
- * Determines if a given action is allowed for a signature block.
- * @param signature - The signature block.
- * @param signatureDecodeFn - The function used to decode the signature.
- * @param action - The action to be checked.
- * @returns True if the action is allowed, false otherwise.
- */
-export declare function signatureBlocksAction(signature: Buffer, signatureDecodeFn: SignatureDecodeFunc, action: string): boolean;
export declare function check32Bit(num: number): void;
export declare function checkFees(psbt: Psbt, cache: PsbtCache, opts: PsbtOpts): void;
export declare function getSignersFromHD(inputIndex: number, inputs: PsbtInput[], hdKeyPair: HDSigner | HDSignerAsync): Array;
export declare function range(n: number): number[];
export declare function isPubkeyLike(buf: Buffer): boolean;
-export {};
diff --git a/src/psbt/psbtutils.js b/src/psbt/psbtutils.js
index cf5b30b28..152fcb820 100644
--- a/src/psbt/psbtutils.js
+++ b/src/psbt/psbtutils.js
@@ -5,96 +5,9 @@ exports.isPubkeyLike =
exports.getSignersFromHD =
exports.checkFees =
exports.check32Bit =
- exports.signatureBlocksAction =
- exports.checkInputForSig =
void 0;
const bscript = require('../script');
-const transaction_1 = require('../transaction');
const utils_1 = require('bip174/src/lib/utils');
-/**
- * Checks if an input contains a signature for a specific action.
- * @param input - The input to check.
- * @param action - The action to check for.
- * @returns A boolean indicating whether the input contains a signature for the specified action.
- */
-function checkInputForSig(input, action) {
- const pSigs = extractPartialSigs(input);
- return pSigs.some(pSig =>
- signatureBlocksAction(pSig, bscript.signature.decode, action),
- );
-}
-exports.checkInputForSig = checkInputForSig;
-/**
- * Determines if a given action is allowed for a signature block.
- * @param signature - The signature block.
- * @param signatureDecodeFn - The function used to decode the signature.
- * @param action - The action to be checked.
- * @returns True if the action is allowed, false otherwise.
- */
-function signatureBlocksAction(signature, signatureDecodeFn, action) {
- const { hashType } = signatureDecodeFn(signature);
- const whitelist = [];
- const isAnyoneCanPay =
- hashType & transaction_1.Transaction.SIGHASH_ANYONECANPAY;
- if (isAnyoneCanPay) whitelist.push('addInput');
- const hashMod = hashType & 0x1f;
- switch (hashMod) {
- case transaction_1.Transaction.SIGHASH_ALL:
- break;
- case transaction_1.Transaction.SIGHASH_SINGLE:
- case transaction_1.Transaction.SIGHASH_NONE:
- whitelist.push('addOutput');
- whitelist.push('setInputSequence');
- break;
- }
- if (whitelist.indexOf(action) === -1) {
- return true;
- }
- return false;
-}
-exports.signatureBlocksAction = signatureBlocksAction;
-/**
- * Extracts the signatures from a PsbtInput object.
- * If the input has partial signatures, it returns an array of the signatures.
- * If the input does not have partial signatures, it checks if it has a finalScriptSig or finalScriptWitness.
- * If it does, it extracts the signatures from the final scripts and returns them.
- * If none of the above conditions are met, it returns an empty array.
- *
- * @param input - The PsbtInput object from which to extract the signatures.
- * @returns An array of signatures extracted from the PsbtInput object.
- */
-function extractPartialSigs(input) {
- let pSigs = [];
- if ((input.partialSig || []).length === 0) {
- if (!input.finalScriptSig && !input.finalScriptWitness) return [];
- pSigs = getPsigsFromInputFinalScripts(input);
- } else {
- pSigs = input.partialSig;
- }
- return pSigs.map(p => p.signature);
-}
-/**
- * Retrieves the partial signatures (Psigs) from the input's final scripts.
- * Psigs are extracted from both the final scriptSig and final scriptWitness of the input.
- * Only canonical script signatures are considered.
- *
- * @param input - The PsbtInput object representing the input.
- * @returns An array of PartialSig objects containing the extracted Psigs.
- */
-function getPsigsFromInputFinalScripts(input) {
- const scriptItems = !input.finalScriptSig
- ? []
- : bscript.decompile(input.finalScriptSig) || [];
- const witnessItems = !input.finalScriptWitness
- ? []
- : bscript.decompile(input.finalScriptWitness) || [];
- return scriptItems
- .concat(witnessItems)
- .filter(item => {
- return Buffer.isBuffer(item) && bscript.isCanonicalScriptSignature(item);
- })
- .map(sig => ({ signature: sig }));
-}
function check32Bit(num) {
if (
typeof num !== 'number' ||
diff --git a/ts_src/psbt/bip371.ts b/ts_src/psbt/bip371.ts
index c2dda4d7f..ed8801dd5 100644
--- a/ts_src/psbt/bip371.ts
+++ b/ts_src/psbt/bip371.ts
@@ -20,8 +20,11 @@ import {
} from '../payments/bip341';
import { isP2TR, p2tr } from '../payments';
-import { signatureBlocksAction } from './psbtutils';
-import { pubkeyPositionInScript, witnessStackToScriptWitness } from './input/script';
+import {
+ pubkeyPositionInScript,
+ witnessStackToScriptWitness,
+} from './input/script';
+import { signatureBlocksAction } from './global/sign';
export const toXOnly = (pubKey: Buffer) =>
pubKey.length === 32 ? pubKey : pubKey.slice(1, 33);
diff --git a/ts_src/psbt/global/cache.ts b/ts_src/psbt/global/cache.ts
index 2420accf0..d72e79a18 100644
--- a/ts_src/psbt/global/cache.ts
+++ b/ts_src/psbt/global/cache.ts
@@ -1,9 +1,9 @@
-import { PsbtInput } from "bip174/src/lib/interfaces";
-import { reverseBuffer } from "../../bufferutils";
-import { PsbtCache, TxCacheNumberKey } from "../interfaces";
-import { Transaction } from "../../transaction";
-import { isFinalized } from ".";
-import { inputFinalizeGetAmts } from "../input";
+import { PsbtInput } from 'bip174/src/lib/interfaces';
+import { reverseBuffer } from '../../bufferutils';
+import { PsbtCache, TxCacheNumberKey } from '../interfaces';
+import { Transaction } from '../../transaction';
+import { isFinalized } from '.';
+import { inputFinalizeGetAmts } from '../input';
export function checkCache(cache: PsbtCache): void {
if (cache.__UNSAFE_SIGN_NONSEGWIT !== false) {
@@ -86,4 +86,4 @@ export function addNonWitnessTxCache(
self.__NON_WITNESS_UTXO_BUF_CACHE[selfIndex] = data;
},
});
-}
\ No newline at end of file
+}
diff --git a/ts_src/psbt/global/hash.ts b/ts_src/psbt/global/hash.ts
index acb76012b..5979af64d 100644
--- a/ts_src/psbt/global/hash.ts
+++ b/ts_src/psbt/global/hash.ts
@@ -5,7 +5,7 @@ import {
checkScriptForPubkey,
getMeaningfulScript,
getScriptAndAmountFromUtxo,
- pubkeyInScript
+ pubkeyInScript,
} from '../input/script';
import { Output, Transaction } from '../../transaction';
import { nonWitnessUtxoTxFromCache } from './cache';
diff --git a/ts_src/psbt/global/index.ts b/ts_src/psbt/global/index.ts
index 112db7bce..1040f8717 100644
--- a/ts_src/psbt/global/index.ts
+++ b/ts_src/psbt/global/index.ts
@@ -5,10 +5,8 @@ import {
} from 'bip174/src/lib/interfaces';
import { hasSigs } from './sign';
import * as payments from '../../payments';
-import { HDSigner, ScriptType } from '../interfaces';
-import { witnessStackToScriptWitness } from '../input/script';
-
-const { isP2MS, isP2PK, isP2PKH, isP2WPKH } = payments;
+import { HDSigner } from '../interfaces';
+import { classifyScript, witnessStackToScriptWitness } from '../input/script';
export function getFinalScripts(
inputIndex: number,
@@ -139,14 +137,6 @@ function getSortedSigs(script: Buffer, partialSig: PartialSig[]): Buffer[] {
.filter(v => !!v);
}
-function classifyScript(script: Buffer): ScriptType {
- if (isP2WPKH(script)) return 'witnesspubkeyhash';
- if (isP2PKH(script)) return 'pubkeyhash';
- if (isP2MS(script)) return 'multisig';
- if (isP2PK(script)) return 'pubkey';
- return 'nonstandard';
-}
-
export function canFinalize(
input: PsbtInput,
script: Buffer,
diff --git a/ts_src/psbt/global/sign.ts b/ts_src/psbt/global/sign.ts
index 873ada15a..d293aca5b 100644
--- a/ts_src/psbt/global/sign.ts
+++ b/ts_src/psbt/global/sign.ts
@@ -1,5 +1,7 @@
-import { PsbtInput } from "bip174/src/lib/interfaces";
+import { PartialSig, PsbtInput } from 'bip174/src/lib/interfaces';
import * as script from '../../script';
+import { Transaction } from '../../transaction';
+import { SignatureDecodeFunc } from '../interfaces';
export function hasSigs(
neededSigs: number,
@@ -41,6 +43,95 @@ export function isSigLike(buf: Buffer): boolean {
return script.isCanonicalScriptSignature(buf);
}
+/**
+ * Checks if an input contains a signature for a specific action.
+ * @param input - The input to check.
+ * @param action - The action to check for.
+ * @returns A boolean indicating whether the input contains a signature for the specified action.
+ */
+export function checkInputForSig(input: PsbtInput, action: string): boolean {
+ const pSigs = extractPartialSigs(input);
+ return pSigs.some(pSig =>
+ signatureBlocksAction(pSig, script.signature.decode, action),
+ );
+}
+
+/**
+ * Determines if a given action is allowed for a signature block.
+ * @param signature - The signature block.
+ * @param signatureDecodeFn - The function used to decode the signature.
+ * @param action - The action to be checked.
+ * @returns True if the action is allowed, false otherwise.
+ */
+export function signatureBlocksAction(
+ signature: Buffer,
+ signatureDecodeFn: SignatureDecodeFunc,
+ action: string,
+): boolean {
+ const { hashType } = signatureDecodeFn(signature);
+ const whitelist: string[] = [];
+ const isAnyoneCanPay = hashType & Transaction.SIGHASH_ANYONECANPAY;
+ if (isAnyoneCanPay) whitelist.push('addInput');
+ const hashMod = hashType & 0x1f;
+ switch (hashMod) {
+ case Transaction.SIGHASH_ALL:
+ break;
+ case Transaction.SIGHASH_SINGLE:
+ case Transaction.SIGHASH_NONE:
+ whitelist.push('addOutput');
+ whitelist.push('setInputSequence');
+ break;
+ }
+ if (whitelist.indexOf(action) === -1) {
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Extracts the signatures from a PsbtInput object.
+ * If the input has partial signatures, it returns an array of the signatures.
+ * If the input does not have partial signatures, it checks if it has a finalScriptSig or finalScriptWitness.
+ * If it does, it extracts the signatures from the final scripts and returns them.
+ * If none of the above conditions are met, it returns an empty array.
+ *
+ * @param input - The PsbtInput object from which to extract the signatures.
+ * @returns An array of signatures extracted from the PsbtInput object.
+ */
+function extractPartialSigs(input: PsbtInput): Buffer[] {
+ let pSigs: PartialSig[] = [];
+ if ((input.partialSig || []).length === 0) {
+ if (!input.finalScriptSig && !input.finalScriptWitness) return [];
+ pSigs = getPsigsFromInputFinalScripts(input);
+ } else {
+ pSigs = input.partialSig!;
+ }
+ return pSigs.map(p => p.signature);
+}
+
+/**
+ * Retrieves the partial signatures (Psigs) from the input's final scripts.
+ * Psigs are extracted from both the final scriptSig and final scriptWitness of the input.
+ * Only canonical script signatures are considered.
+ *
+ * @param input - The PsbtInput object representing the input.
+ * @returns An array of PartialSig objects containing the extracted Psigs.
+ */
+function getPsigsFromInputFinalScripts(input: PsbtInput): PartialSig[] {
+ const scriptItems = !input.finalScriptSig
+ ? []
+ : script.decompile(input.finalScriptSig) || [];
+ const witnessItems = !input.finalScriptWitness
+ ? []
+ : script.decompile(input.finalScriptWitness) || [];
+ return scriptItems
+ .concat(witnessItems)
+ .filter(item => {
+ return Buffer.isBuffer(item) && script.isCanonicalScriptSignature(item);
+ })
+ .map(sig => ({ signature: sig })) as PartialSig[];
+}
+
function compressPubkey(pubkey: Buffer): Buffer {
if (pubkey.length === 65) {
const parity = pubkey[64] & 1;
@@ -49,4 +140,4 @@ function compressPubkey(pubkey: Buffer): Buffer {
return newKey;
}
return pubkey.slice();
-}
\ No newline at end of file
+}
diff --git a/ts_src/psbt/input/index.ts b/ts_src/psbt/input/index.ts
index 7e7426283..822ab0f70 100644
--- a/ts_src/psbt/input/index.ts
+++ b/ts_src/psbt/input/index.ts
@@ -1,6 +1,6 @@
import { PsbtInput } from 'bip174/src/lib/interfaces';
import { checkTaprootInputForSigs, isTaprootInput } from '../bip371';
-import { checkInputForSig } from '../psbtutils';
+import { checkInputForSig } from '../global/sign';
import { Output, Transaction } from '../../transaction';
import { PsbtCache } from '../interfaces';
import { checkTxInputCache, nonWitnessUtxoTxFromCache } from '../global/cache';
diff --git a/ts_src/psbt/input/script.ts b/ts_src/psbt/input/script.ts
index 19ce0d161..e598569d8 100644
--- a/ts_src/psbt/input/script.ts
+++ b/ts_src/psbt/input/script.ts
@@ -1,14 +1,15 @@
-import { PsbtInput } from "bip174/src/lib/interfaces";
-import { varuint } from "../../bufferutils";
-import * as payments from "../../payments";
-import { GetScriptReturn, PsbtCache, ScriptType } from "../interfaces";
-import { nonWitnessUtxoTxFromCache } from "../global/cache";
-import { hash160 } from "../../crypto";
+import { PsbtInput } from 'bip174/src/lib/interfaces';
+import { varuint } from '../../bufferutils';
+import * as payments from '../../payments';
+import { GetScriptReturn, PsbtCache, ScriptType } from '../interfaces';
+import { nonWitnessUtxoTxFromCache } from '../global/cache';
+import { hash160 } from '../../crypto';
import * as bscript from '../../script';
-import { isPubkeyLike } from "../psbtutils";
-import { isSigLike } from "../global/sign";
+import { isPubkeyLike } from '../psbtutils';
+import { isSigLike } from '../global/sign';
-const {isP2MS, isP2PK, isP2PKH, isP2SHScript, isP2WPKH, isP2WSHScript} = payments;
+const { isP2MS, isP2PK, isP2PKH, isP2SHScript, isP2WPKH, isP2WSHScript } =
+ payments;
export function getMeaningfulScript(
script: Buffer,
@@ -53,10 +54,10 @@ export function getMeaningfulScript(
type: isP2SHP2WSH
? 'p2sh-p2wsh'
: isP2SH
- ? 'p2sh'
- : isP2WSH
- ? 'p2wsh'
- : 'raw',
+ ? 'p2sh'
+ : isP2WSH
+ ? 'p2wsh'
+ : 'raw',
};
}
@@ -309,4 +310,4 @@ const checkRedeemScript = scriptCheckerFactory(payments.p2sh, 'Redeem script');
const checkWitnessScript = scriptCheckerFactory(
payments.p2wsh,
'Witness script',
-);
\ No newline at end of file
+);
diff --git a/ts_src/psbt/interfaces.ts b/ts_src/psbt/interfaces.ts
index d0ded62c1..3c949380c 100644
--- a/ts_src/psbt/interfaces.ts
+++ b/ts_src/psbt/interfaces.ts
@@ -1,9 +1,6 @@
import { Network } from '../networks';
import { Transaction } from '../transaction';
-import {
- PsbtInput,
- PsbtOutput,
-} from 'bip174/src/lib/interfaces';
+import { PsbtInput, PsbtOutput } from 'bip174/src/lib/interfaces';
export interface PsbtCache {
__NON_WITNESS_UTXO_TX_CACHE: Transaction[];
@@ -26,9 +23,11 @@ export interface PsbtOpts {
maximumFeeRate: number;
}
-export interface PsbtInputExtended extends PsbtInput, TransactionInput { }
+export interface PsbtInputExtended extends PsbtInput, TransactionInput {}
-export type PsbtOutputExtended = PsbtOutputExtendedAddress | PsbtOutputExtendedScript;
+export type PsbtOutputExtended =
+ | PsbtOutputExtendedAddress
+ | PsbtOutputExtendedScript;
export interface PsbtOutputExtendedAddress extends PsbtOutput {
address: string;
@@ -95,7 +94,6 @@ export interface GetScriptReturn {
isP2WSH: boolean;
}
-
export interface TransactionInput {
hash: string | Buffer;
index: number;
@@ -175,4 +173,9 @@ export type ScriptType =
| 'pubkeyhash'
| 'multisig'
| 'pubkey'
- | 'nonstandard';
\ No newline at end of file
+ | 'nonstandard';
+
+export type SignatureDecodeFunc = (buffer: Buffer) => {
+ signature: Buffer;
+ hashType: number;
+};
diff --git a/ts_src/psbt/psbtutils.ts b/ts_src/psbt/psbtutils.ts
index de2ab4287..84d35dcf6 100644
--- a/ts_src/psbt/psbtutils.ts
+++ b/ts_src/psbt/psbtutils.ts
@@ -1,103 +1,16 @@
-import { PartialSig, PsbtInput } from 'bip174/src/lib/interfaces';
+import { PsbtInput } from 'bip174/src/lib/interfaces';
import * as bscript from '../script';
-import { Transaction } from '../transaction';
-import { HDSigner, HDSignerAsync, PsbtCache, PsbtOpts, Signer, SignerAsync } from './interfaces';
+import {
+ HDSigner,
+ HDSignerAsync,
+ PsbtCache,
+ PsbtOpts,
+ Signer,
+ SignerAsync,
+} from './interfaces';
import { Psbt } from '../psbt';
import { checkForInput } from 'bip174/src/lib/utils';
-/**
- * Checks if an input contains a signature for a specific action.
- * @param input - The input to check.
- * @param action - The action to check for.
- * @returns A boolean indicating whether the input contains a signature for the specified action.
- */
-export function checkInputForSig(input: PsbtInput, action: string): boolean {
- const pSigs = extractPartialSigs(input);
- return pSigs.some(pSig =>
- signatureBlocksAction(pSig, bscript.signature.decode, action),
- );
-}
-
-type SignatureDecodeFunc = (buffer: Buffer) => {
- signature: Buffer;
- hashType: number;
-};
-/**
- * Determines if a given action is allowed for a signature block.
- * @param signature - The signature block.
- * @param signatureDecodeFn - The function used to decode the signature.
- * @param action - The action to be checked.
- * @returns True if the action is allowed, false otherwise.
- */
-export function signatureBlocksAction(
- signature: Buffer,
- signatureDecodeFn: SignatureDecodeFunc,
- action: string,
-): boolean {
- const { hashType } = signatureDecodeFn(signature);
- const whitelist: string[] = [];
- const isAnyoneCanPay = hashType & Transaction.SIGHASH_ANYONECANPAY;
- if (isAnyoneCanPay) whitelist.push('addInput');
- const hashMod = hashType & 0x1f;
- switch (hashMod) {
- case Transaction.SIGHASH_ALL:
- break;
- case Transaction.SIGHASH_SINGLE:
- case Transaction.SIGHASH_NONE:
- whitelist.push('addOutput');
- whitelist.push('setInputSequence');
- break;
- }
- if (whitelist.indexOf(action) === -1) {
- return true;
- }
- return false;
-}
-
-/**
- * Extracts the signatures from a PsbtInput object.
- * If the input has partial signatures, it returns an array of the signatures.
- * If the input does not have partial signatures, it checks if it has a finalScriptSig or finalScriptWitness.
- * If it does, it extracts the signatures from the final scripts and returns them.
- * If none of the above conditions are met, it returns an empty array.
- *
- * @param input - The PsbtInput object from which to extract the signatures.
- * @returns An array of signatures extracted from the PsbtInput object.
- */
-function extractPartialSigs(input: PsbtInput): Buffer[] {
- let pSigs: PartialSig[] = [];
- if ((input.partialSig || []).length === 0) {
- if (!input.finalScriptSig && !input.finalScriptWitness) return [];
- pSigs = getPsigsFromInputFinalScripts(input);
- } else {
- pSigs = input.partialSig!;
- }
- return pSigs.map(p => p.signature);
-}
-
-/**
- * Retrieves the partial signatures (Psigs) from the input's final scripts.
- * Psigs are extracted from both the final scriptSig and final scriptWitness of the input.
- * Only canonical script signatures are considered.
- *
- * @param input - The PsbtInput object representing the input.
- * @returns An array of PartialSig objects containing the extracted Psigs.
- */
-function getPsigsFromInputFinalScripts(input: PsbtInput): PartialSig[] {
- const scriptItems = !input.finalScriptSig
- ? []
- : bscript.decompile(input.finalScriptSig) || [];
- const witnessItems = !input.finalScriptWitness
- ? []
- : bscript.decompile(input.finalScriptWitness) || [];
- return scriptItems
- .concat(witnessItems)
- .filter(item => {
- return Buffer.isBuffer(item) && bscript.isCanonicalScriptSignature(item);
- })
- .map(sig => ({ signature: sig })) as PartialSig[];
-}
-
export function check32Bit(num: number): void {
if (
typeof num !== 'number' ||
@@ -163,4 +76,4 @@ export function range(n: number): number[] {
export function isPubkeyLike(buf: Buffer): boolean {
return buf.length === 33 && bscript.isCanonicalPubKey(buf);
-}
\ No newline at end of file
+}