Skip to content

Commit 12180b0

Browse files
OttoAllmendingerllm-git
andcommitted
feat(wasm-utxo): add signature verification methods to BitGoPsbt
Add two methods for verifying transaction signatures: - verifySignature - Verify ECDSA, Schnorr, or MuSig2 signatures based on xpub derivation path found in the PSBT - verifyReplayProtectionSignature - Verify signatures in replay protection inputs (P2SH-P2PK) These methods enable transaction validation without requiring full re-signing, which is particularly useful when checking the signing state of PSBTs across different types of inputs. Issue: BTC-2652 Co-authored-by: llm-git <[email protected]>
1 parent 749031e commit 12180b0

File tree

8 files changed

+1157
-99
lines changed

8 files changed

+1157
-99
lines changed

packages/wasm-utxo/js/fixedScriptWallet.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,44 @@ export class BitGoPsbt {
129129
parseOutputsWithWalletKeys(walletKeys: WalletKeys): ParsedOutput[] {
130130
return this.wasm.parse_outputs_with_wallet_keys(walletKeys);
131131
}
132+
133+
/**
134+
* Verify if a valid signature exists for a given extended public key at the specified input index.
135+
*
136+
* This method derives the public key from the xpub using the derivation path found in the
137+
* PSBT input, then verifies the signature. It supports:
138+
* - ECDSA signatures (for legacy/SegWit inputs)
139+
* - Schnorr signatures (for Taproot script path inputs)
140+
* - MuSig2 partial signatures (for Taproot keypath MuSig2 inputs)
141+
*
142+
* @param inputIndex - The index of the input to check (0-based)
143+
* @param xpub - The extended public key as a base58-encoded string
144+
* @returns true if a valid signature exists, false if no signature exists
145+
* @throws Error if input index is out of bounds, xpub is invalid, or verification fails
146+
*/
147+
verifySignature(inputIndex: number, xpub: string): boolean {
148+
return this.wasm.verify_signature(inputIndex, xpub);
149+
}
150+
151+
/**
152+
* Verify if a replay protection input has a valid signature.
153+
*
154+
* This method checks if a given input is a replay protection input (like P2shP2pk) and verifies
155+
* the signature. Replay protection inputs don't use standard derivation paths, so this method
156+
* verifies signatures without deriving from xpub.
157+
*
158+
* For P2PK replay protection inputs, this:
159+
* - Extracts the signature from final_script_sig
160+
* - Extracts the public key from redeem_script
161+
* - Computes the legacy P2SH sighash
162+
* - Verifies the ECDSA signature cryptographically
163+
*
164+
* @param inputIndex - The index of the input to check (0-based)
165+
* @param replayProtection - Scripts that identify replay protection inputs (same format as parseTransactionWithWalletKeys)
166+
* @returns true if the input is a replay protection input and has a valid signature, false if no valid signature
167+
* @throws Error if the input is not a replay protection input, index is out of bounds, or scripts are invalid
168+
*/
169+
verifyReplayProtectionSignature(inputIndex: number, replayProtection: ReplayProtection): boolean {
170+
return this.wasm.verify_replay_protection_signature(inputIndex, replayProtection);
171+
}
132172
}

0 commit comments

Comments
 (0)