{"version":3,"file":"verifyKeyPathSchnorrSignature-Cr5T4Aym.cjs","sources":["../src/tbv/core/primitives/psbt/peginInput.ts","../src/tbv/core/utils/witness/witnessStack.ts","../src/tbv/core/primitives/psbt/verifyP2wpkhEcdsaSignature.ts","../src/tbv/core/primitives/psbt/verifyKeyPathSchnorrSignature.ts"],"sourcesContent":["/**\n * PegIn Input PSBT Builder\n *\n * Builds the PSBT for the depositor to sign the PegIn transaction's HTLC input\n * (Pre-PegIn HTLC leaf 0 — the hashlock + all-party script).\n *\n * This is the \"Sign Pegin transaction HTLC leaf 0 input\" step in the pre-pegin\n * flow. The depositor signs input 0 of the PegIn transaction,\n * which spends output 0 of the funded Pre-PegIn transaction via script-path.\n *\n * @module primitives/psbt/peginInput\n */\n\nimport {\n  getPrePeginHtlcConnectorInfo,\n  tapInternalPubkey,\n  type Network,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Psbt, Transaction, payments } from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\nimport {\n  TAPSCRIPT_LEAF_VERSION,\n  assertEccInitialized,\n  hexToUint8Array,\n  stripHexPrefix,\n  uint8ArrayToHex,\n} from \"../utils/bitcoin\";\n\n/**\n * Parameters for building the PegIn input PSBT\n */\nexport interface BuildPeginInputPsbtParams {\n  /**\n   * Vault core (tx-graph) version the Pre-PegIn was built with. Must match\n   * the version passed to buildPrePeginPsbt() so the HTLC connector scripts\n   * are derived for the same graph.\n   */\n  vaultCoreVersion: number;\n  /**\n   * PegIn transaction hex (1 input spending Pre-PegIn HTLC output 0).\n   * Returned by buildPeginTxFromFundedPrePegin().\n   */\n  peginTxHex: string;\n  /**\n   * Funded Pre-PegIn transaction hex.\n   * Used to look up the HTLC output that the PegIn input spends.\n   */\n  fundedPrePeginTxHex: string;\n  /** Depositor's BTC public key (x-only, 64-char hex) */\n  depositorPubkey: string;\n  /** Vault provider's BTC public key (x-only, 64-char hex) */\n  vaultProviderPubkey: string;\n  /** Vault keeper BTC public keys (x-only, 64-char hex) */\n  vaultKeeperPubkeys: string[];\n  /** Universal challenger BTC public keys (x-only, 64-char hex) */\n  universalChallengerPubkeys: string[];\n  /** SHA256 hash commitment (64 hex chars = 32 bytes) */\n  hashlock: string;\n  /** CSV timelock in blocks for the HTLC refund path */\n  timelockRefund: number;\n  /** Bitcoin network */\n  network: Network;\n}\n\n/**\n * Result of building the PegIn input PSBT\n */\nexport interface BuildPeginInputPsbtResult {\n  /** PSBT hex for the depositor to sign */\n  psbtHex: string;\n}\n\n/**\n * Build PSBT for depositor to sign the PegIn transaction's HTLC leaf 0 input.\n *\n * The PegIn transaction spends the Pre-PegIn HTLC output (output 0) via the\n * hashlock + all-party script (leaf 0). The depositor provides one of the required\n * signatures; the vault provider and keepers provide theirs separately via the\n * signPeginInput RPC.\n *\n * The PSBT uses Taproot script-path spending:\n * - witnessUtxo: the Pre-PegIn HTLC output\n * - tapLeafScript: hashlock leaf script + control block\n * - tapInternalKey: NUMS unspendable key (BIP-341 nothing-up-my-sleeve)\n *\n * @param params - PegIn input PSBT parameters\n * @returns PSBT hex ready for depositor signing\n * @throws If PegIn tx does not have exactly 1 input\n * @throws If PegIn input does not reference the Pre-PegIn HTLC output\n * @throws If Pre-PegIn tx output 0 is not found\n */\nexport async function buildPeginInputPsbt(\n  params: BuildPeginInputPsbtParams,\n): Promise<BuildPeginInputPsbtResult> {\n  const peginTxHex = stripHexPrefix(params.peginTxHex);\n  const fundedPrePeginTxHex = stripHexPrefix(params.fundedPrePeginTxHex);\n\n  const htlcConnector = await getPrePeginHtlcConnectorInfo({\n    txGraphVersion: params.vaultCoreVersion,\n    depositorPubkey: params.depositorPubkey,\n    vaultProviderPubkey: params.vaultProviderPubkey,\n    vaultKeeperPubkeys: params.vaultKeeperPubkeys,\n    universalChallengerPubkeys: params.universalChallengerPubkeys,\n    hashlock: params.hashlock,\n    timelockRefund: params.timelockRefund,\n    network: params.network,\n  });\n\n  const peginTx = Transaction.fromHex(peginTxHex);\n  const prePeginTx = Transaction.fromHex(fundedPrePeginTxHex);\n\n  if (peginTx.ins.length !== 1) {\n    throw new Error(\n      `PegIn transaction must have exactly 1 input, got ${peginTx.ins.length}`,\n    );\n  }\n\n  const peginInput = peginTx.ins[0];\n\n  // Verify PegIn input 0 spends Pre-PegIn output 0\n  const prePeginTxid = prePeginTx.getId();\n  const peginInputTxid = uint8ArrayToHex(\n    new Uint8Array(peginInput.hash).slice().reverse(),\n  );\n\n  if (peginInputTxid !== prePeginTxid) {\n    throw new Error(\n      `PegIn input does not reference the Pre-PegIn transaction. ` +\n        `Expected ${prePeginTxid}, got ${peginInputTxid}`,\n    );\n  }\n\n  const htlcOutput = prePeginTx.outs[peginInput.index];\n  if (!htlcOutput) {\n    throw new Error(\n      `Pre-PegIn output ${peginInput.index} not found ` +\n        `(Pre-PegIn has ${prePeginTx.outs.length} outputs)`,\n    );\n  }\n\n  const hashlockScript = hexToUint8Array(htlcConnector.hashlockScript);\n  const hashlockControlBlock = hexToUint8Array(\n    htlcConnector.hashlockControlBlock,\n  );\n\n  // Merkle root recomputed from the two connector leaves — inert for extension\n  // wallets, byte-compared by hardware that recomputes it. The closed loop\n  // below (derived P2TR == the funded HTLC spk) is what makes it trustworthy.\n  assertEccInitialized();\n  const htlcTaptree = payments.p2tr({\n    internalPubkey: Buffer.from(tapInternalPubkey),\n    scriptTree: [\n      { output: Buffer.from(hashlockScript), version: TAPSCRIPT_LEAF_VERSION },\n      {\n        output: Buffer.from(hexToUint8Array(htlcConnector.refundScript)),\n        version: TAPSCRIPT_LEAF_VERSION,\n      },\n    ],\n  });\n  if (!htlcTaptree.output?.equals(htlcOutput.script) || !htlcTaptree.hash) {\n    throw new Error(\n      \"PegIn HTLC taptree mismatch: the recomputed 2-leaf tree does not \" +\n        \"reproduce the funded Pre-PegIn HTLC scriptPubKey; refusing to sign.\",\n    );\n  }\n\n  const psbt = new Psbt();\n  psbt.setVersion(peginTx.version);\n  psbt.setLocktime(peginTx.locktime);\n\n  // Input 0: PegIn input spending Pre-PegIn HTLC output 0 via hashlock leaf (leaf 0).\n  // The depositor signs using Taproot script-path spending. bitcoinjs\n  // re-verifies leaf-in-tree consistency (control block vs tapMerkleRoot)\n  // inside addInput — a second independent check.\n  psbt.addInput({\n    hash: peginInput.hash,\n    index: peginInput.index,\n    sequence: peginInput.sequence,\n    witnessUtxo: {\n      script: htlcOutput.script,\n      value: htlcOutput.value,\n    },\n    tapLeafScript: [\n      {\n        leafVersion: TAPSCRIPT_LEAF_VERSION,\n        script: Buffer.from(hashlockScript),\n        controlBlock: Buffer.from(hashlockControlBlock),\n      },\n    ],\n    tapInternalKey: Buffer.from(tapInternalPubkey),\n    tapMerkleRoot: htlcTaptree.hash,\n    // sighashType omitted — defaults to SIGHASH_DEFAULT (0x00) for Taproot\n  });\n\n  for (const output of peginTx.outs) {\n    psbt.addOutput({\n      script: output.script,\n      value: output.value,\n    });\n  }\n\n  return { psbtHex: psbt.toHex() };\n}\n\n/**\n * Extract the depositor's Schnorr signature from a signed PegIn input PSBT.\n *\n * Supports non-finalized PSBTs with tapScriptSig entries. Finalized PSBTs are\n * rejected because the witness stack does not reliably identify the depositor\n * signature by public key.\n *\n * PegIn input signatures must use implicit Taproot SIGHASH_DEFAULT, which is\n * encoded by omitting the sighash byte. Signatures with an appended sighash byte\n * are rejected rather than stripped.\n *\n * @param signedPsbtHex - Signed PSBT hex\n * @param depositorPubkey - Depositor's x-only public key (64-char hex)\n * @returns 64-byte Schnorr signature (128 hex chars, no sighash flag)\n * @throws If no signature is found for the depositor's key\n */\nexport function extractPeginInputSignature(\n  signedPsbtHex: string,\n  depositorPubkey: string,\n): string {\n  const signedPsbt = Psbt.fromHex(signedPsbtHex);\n  const input = signedPsbt.data.inputs[0];\n\n  if (!input) {\n    throw new Error(\"PegIn PSBT has no inputs\");\n  }\n\n  // Non-finalized PSBT — extract from tapScriptSig\n  if (input.tapScriptSig && input.tapScriptSig.length > 0) {\n    const depositorPubkeyBytes = Buffer.from(hexToUint8Array(depositorPubkey));\n\n    for (const sigEntry of input.tapScriptSig) {\n      if (sigEntry.pubkey.equals(depositorPubkeyBytes)) {\n        return extractSchnorrSig(sigEntry.signature);\n      }\n    }\n\n    throw new Error(\n      `No PegIn input signature found for depositor pubkey: ${depositorPubkey}`,\n    );\n  }\n\n  // Finalized PSBT — the witness stack order depends on the wallet's finalizer,\n  // so we cannot reliably pick the depositor's signature by position. Require\n  // the non-finalized tapScriptSig path which identifies signatures by pubkey.\n  if (input.finalScriptWitness && input.finalScriptWitness.length > 0) {\n    throw new Error(\n      \"PegIn input PSBT is already finalized. Cannot reliably extract the \" +\n        \"depositor signature from the witness stack. Ensure the wallet returns \" +\n        \"a non-finalized PSBT with tapScriptSig entries.\",\n    );\n  }\n\n  throw new Error(\n    \"No tapScriptSig or finalScriptWitness found in signed PegIn input PSBT\",\n  );\n}\n\n/**\n * Finalize a signed PegIn input PSBT and return the depositor-signed transaction hex.\n *\n * The default tapscript finalizer builds the full witness stack [sig, script, controlBlock]\n * that vaultd requires when verifying the depositor signature on-chain.\n *\n * @param signedPsbtHex - Non-finalized signed PSBT hex (returned by wallet with autoFinalized: false)\n * @returns Depositor-signed PegIn transaction hex with full taproot witness stack\n */\nexport function finalizePeginInputPsbt(signedPsbtHex: string): string {\n  const psbt = Psbt.fromHex(signedPsbtHex);\n\n  // Some wallets (UniSat, OKX) ignore autoFinalized: false and return\n  // already-finalized PSBTs. finalizeAllInputs() throws in that case,\n  // so fall back to verifying the wallet already finalized all inputs.\n  try {\n    psbt.finalizeAllInputs();\n  } catch (e) {\n    const allFinalized = psbt.data.inputs.every(\n      (inp) => inp.finalScriptWitness || inp.finalScriptSig,\n    );\n    if (!allFinalized) {\n      throw new Error(\n        `PSBT finalization failed and wallet did not auto-finalize: ${e}`,\n      );\n    }\n  }\n\n  return psbt.extractTransaction().toHex();\n}\n\n/**\n * Extract and validate a 64-byte Schnorr signature.\n * PegIn input signatures must use implicit Taproot SIGHASH_DEFAULT, which is\n * encoded by omitting the sighash byte. Reject 65-byte signatures instead of\n * stripping the sighash byte because it changes the signed Taproot message.\n * @internal\n */\nexport function extractSchnorrSig(sig: Uint8Array): string {\n  if (sig.length === 64) {\n    return uint8ArrayToHex(new Uint8Array(sig));\n  }\n  if (sig.length === 65) {\n    throw new Error(\n      `Unexpected sighash byte 0x${sig[64].toString(16).padStart(2, \"0\")} in PegIn input signature. ` +\n        \"Expected implicit SIGHASH_DEFAULT as a 64-byte signature.\",\n    );\n  }\n  throw new Error(`Unexpected PegIn input signature length: ${sig.length}`);\n}\n","/**\n * Consensus witness-stack decoding, shared by every module that reads a\n * witness we did not build.\n *\n * Two independent decoders drifted apart before this existed: one accepted\n * non-minimal CompactSize encodings, the other rejected them. vaultd decodes\n * with rust-bitcoin, whose `VarInt::consensus_decode`\n * (0.32.8 `consensus/encode.rs:493-522`) returns `NonMinimalVarInt` for a 0xfd\n * carrying < 0xfd and a 0xfe carrying < 0x10000 — so the strict reading is the\n * only one that matches what the network will accept.\n *\n * @module tbv/core/utils/witness/witnessStack\n */\n\n/** CompactSize discriminators; 0xff (u64) is out of range for a witness. */\nconst COMPACT_SIZE_UINT16_PREFIX = 0xfd;\nconst COMPACT_SIZE_UINT32_PREFIX = 0xfe;\nconst COMPACT_SIZE_UINT16_BYTES = 3;\nconst COMPACT_SIZE_UINT32_BYTES = 5;\nconst COMPACT_SIZE_UINT16_MIN_VALUE = 0xfd;\nconst COMPACT_SIZE_UINT32_MIN_VALUE = 0x10000;\n\n/**\n * Decode a consensus-encoded witness stack: item count, then (len, bytes)*.\n *\n * @param witness - The consensus-encoded witness bytes.\n * @param subject - Names the witness in error messages (e.g. \"finalScriptWitness\").\n * @returns The stack items, as views over `witness`.\n * @throws If the encoding is truncated, non-minimal, out of range, or leaves\n *         trailing bytes.\n */\nexport function decodeWitnessStack(\n  witness: Uint8Array,\n  subject: string,\n): Uint8Array[] {\n  let offset = 0;\n\n  const readCompactSize = (): number => {\n    if (offset >= witness.length) {\n      throw new Error(`${subject} is truncated`);\n    }\n    const first = witness[offset];\n    if (first < COMPACT_SIZE_UINT16_PREFIX) {\n      offset += 1;\n      return first;\n    }\n    if (first === COMPACT_SIZE_UINT16_PREFIX) {\n      if (offset + COMPACT_SIZE_UINT16_BYTES > witness.length) {\n        throw new Error(`${subject} is truncated`);\n      }\n      const value = witness[offset + 1] | (witness[offset + 2] << 8);\n      if (value < COMPACT_SIZE_UINT16_MIN_VALUE) {\n        throw new Error(`${subject} has a non-minimal length encoding`);\n      }\n      offset += COMPACT_SIZE_UINT16_BYTES;\n      return value;\n    }\n    if (first === COMPACT_SIZE_UINT32_PREFIX) {\n      if (offset + COMPACT_SIZE_UINT32_BYTES > witness.length) {\n        throw new Error(`${subject} is truncated`);\n      }\n      const value =\n        (witness[offset + 1] |\n          (witness[offset + 2] << 8) |\n          (witness[offset + 3] << 16) |\n          (witness[offset + 4] << 24)) >>>\n        0;\n      if (value < COMPACT_SIZE_UINT32_MIN_VALUE) {\n        throw new Error(`${subject} has a non-minimal length encoding`);\n      }\n      offset += COMPACT_SIZE_UINT32_BYTES;\n      return value;\n    }\n    throw new Error(`${subject} carries an out-of-range item length`);\n  };\n\n  const count = readCompactSize();\n  const items: Uint8Array[] = [];\n  for (let i = 0; i < count; i++) {\n    const len = readCompactSize();\n    if (offset + len > witness.length) {\n      throw new Error(`${subject} is truncated`);\n    }\n    items.push(witness.subarray(offset, offset + len));\n    offset += len;\n  }\n  if (offset !== witness.length) {\n    throw new Error(`${subject} has trailing bytes`);\n  }\n  return items;\n}\n","/**\n * Far-side verification of P2WPKH ECDSA signatures a wallet returned, over\n * the PSBT we requested (trusted prevouts) — the Native SegWit sibling of\n * `verifyKeyPathSchnorrSignature`. Reference: btc-vault\n * `crates/btc-wallet-remote/src/client.rs:945-1000\n * verify_finalized_p2wpkh_spend`. The wallet's success/finalization is\n * never trusted on its own (CLAUDE.md §8): prevout script and value come\n * from the PSBT we built; only the signature bytes come from the wallet.\n *\n * @module tbv/core/primitives/psbt/verifyP2wpkhEcdsaSignature\n */\n\nimport * as ecc from \"@bitcoin-js/tiny-secp256k1-asmjs\";\nimport {\n  crypto as bcrypto,\n  script as bscript,\n  payments,\n  Psbt,\n  Transaction,\n} from \"bitcoinjs-lib\";\n\nimport { Buffer } from \"buffer\";\n\nimport { decodeWitnessStack } from \"../../utils/witness/witnessStack\";\n\n// P2WPKH scriptPubKey is exactly `OP_0 OP_PUSHBYTES_20 <20-byte key hash>`\n// (BIP-141 witness program v0, 20 bytes).\nconst P2WPKH_SCRIPT_LEN = 22;\nconst OP_0 = 0x00;\nconst OP_PUSHBYTES_20 = 0x14;\nconst P2WPKH_PROGRAM_START = 2;\n\n/** SEC1 compressed pubkey (client.rs:959: \"expected a 33-byte compressed key\"). */\nconst COMPRESSED_PUBKEY_BYTES = 33;\n/** Consensus P2WPKH witness: exactly [signature, pubkey] (client.rs:951-957). */\nconst P2WPKH_WITNESS_ITEMS = 2;\n\n/** Only claim P2WPKH: 22-byte scriptPubKey starting `OP_0 PUSH20`. */\nexport function isP2wpkhScript(\n  script: Uint8Array | undefined,\n): script is Uint8Array {\n  return (\n    script !== undefined &&\n    script.length === P2WPKH_SCRIPT_LEN &&\n    script[0] === OP_0 &&\n    script[1] === OP_PUSHBYTES_20\n  );\n}\n\nfunction bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n  return a.length === b.length && a.every((byte, i) => byte === b[i]);\n}\n\n/** The `[signature, pubkey]` pair of a finalized P2WPKH witness (client.rs:951-957). */\nfunction decodeP2wpkhWitness(\n  finalScriptWitness: Uint8Array,\n  inputIndex: number,\n): { signature: Uint8Array; pubkey: Uint8Array } {\n  const items = decodeWitnessStack(finalScriptWitness, \"finalScriptWitness\");\n  if (items.length !== P2WPKH_WITNESS_ITEMS) {\n    throw new Error(\n      `Returned PSBT input ${inputIndex}: a finalized P2WPKH witness must have ` +\n        `exactly 2 items [signature, pubkey], got ${items.length}.`,\n    );\n  }\n  return { signature: items[0], pubkey: items[1] };\n}\n\nexport interface AssertReturnedP2wpkhSignatureParams {\n  /** Hex of the PSBT we built and sent (trusted prevout script/value). NOT the wallet's. */\n  requestedPsbtHex: string;\n  /** The wallet-returned PSBT input carrying the signature material. */\n  returnedInput: {\n    partialSig?: Array<{ pubkey: Uint8Array; signature: Uint8Array }>;\n    finalScriptWitness?: Uint8Array;\n  };\n  /** Index of the input the signature is for. */\n  inputIndex: number;\n}\n\n/**\n * Assert that the returned input carries a valid P2WPKH ECDSA signature\n * over the BIP-143 sighash of `requestedPsbtHex` input `inputIndex`:\n * `partialSig` (BIP-174: the value is the exact witness-stack signature\n * bytes, the key its pubkey), or the finalized 2-item witness — and when\n * both are present they must be the same bytes.\n *\n * @throws If the requested input is not a P2WPKH spend, no signature was\n *         returned, a finalized witness disagrees with its `partialSig`,\n *         or any check of `verify_finalized_p2wpkh_spend` fails.\n */\nexport function assertReturnedP2wpkhSignature(\n  params: AssertReturnedP2wpkhSignatureParams,\n): void {\n  const { requestedPsbtHex, returnedInput, inputIndex } = params;\n\n  const partials = returnedInput.partialSig;\n  // Consensus allows exactly one signature in a P2WPKH witness, so a second\n  // partialSig entry is ambiguous tampering, not a fallback to pick from.\n  if (partials !== undefined && partials.length > 1) {\n    throw new Error(\n      `Returned PSBT input ${inputIndex}: a P2WPKH input must carry at most one ` +\n        `partial signature, got ${partials.length}.`,\n    );\n  }\n  const partial = partials?.[0];\n  const witness = returnedInput.finalScriptWitness\n    ? decodeP2wpkhWitness(returnedInput.finalScriptWitness, inputIndex)\n    : undefined;\n\n  // Both fields can be present, and the consumers broadcast the WITNESS\n  // bytes — so the two must agree, not just one of them verify (same\n  // rationale as the tapKeySig/witness agreement check).\n  if (\n    partial &&\n    witness &&\n    (!bytesEqual(partial.signature, witness.signature) ||\n      !bytesEqual(partial.pubkey, witness.pubkey))\n  ) {\n    throw new Error(\n      `Returned PSBT input ${inputIndex} finalized witness does not match its partialSig.`,\n    );\n  }\n\n  const material = partial ?? witness;\n  if (!material) {\n    throw new Error(\n      `Returned PSBT input ${inputIndex} carries no P2WPKH signature ` +\n        `(no partialSig, not finalized).`,\n    );\n  }\n\n  assertP2wpkhEcdsaSignature(\n    requestedPsbtHex,\n    material.signature,\n    material.pubkey,\n    inputIndex,\n  );\n}\n\n/**\n * The crypto core, mirroring `verify_finalized_p2wpkh_spend` check by\n * check: pubkey shape and curve membership, hash160(pubkey) == witness\n * program, strict-DER + SIGHASH_ALL-only signature, ECDSA over the\n * BIP-143 sighash recomputed from the REQUESTED prevout.\n */\nfunction assertP2wpkhEcdsaSignature(\n  requestedPsbtHex: string,\n  encodedSignature: Uint8Array,\n  pubkey: Uint8Array,\n  inputIndex: number,\n): void {\n  const psbt = Psbt.fromHex(requestedPsbtHex);\n\n  if (inputIndex < 0 || inputIndex >= psbt.data.inputs.length) {\n    throw new Error(\n      `Input index ${inputIndex} out of range (${psbt.data.inputs.length} inputs).`,\n    );\n  }\n  const prevout = psbt.data.inputs[inputIndex].witnessUtxo;\n  if (!prevout || !isP2wpkhScript(prevout.script)) {\n    throw new Error(\n      `Input ${inputIndex} of the requested PSBT is not a P2WPKH input.`,\n    );\n  }\n\n  // Pubkey: exactly 33 bytes (client.rs:959-965) and a parseable curve\n  // point, as PublicKey::from_slice (client.rs:966-968).\n  if (pubkey.length !== COMPRESSED_PUBKEY_BYTES) {\n    throw new Error(\n      `Returned PSBT input ${inputIndex}: P2WPKH pubkey must be 33 bytes, ` +\n        `got ${pubkey.length}.`,\n    );\n  }\n  if (!ecc.isPointCompressed(pubkey)) {\n    throw new Error(\n      `Returned PSBT input ${inputIndex}: P2WPKH pubkey is not a valid secp256k1 point.`,\n    );\n  }\n\n  // hash160(pubkey) must equal the prevout's witness program — what\n  // consensus checks (client.rs:970-977).\n  const program = prevout.script.subarray(\n    P2WPKH_PROGRAM_START,\n    P2WPKH_SCRIPT_LEN,\n  );\n  if (!bytesEqual(bcrypto.hash160(Buffer.from(pubkey)), program)) {\n    throw new Error(\n      `Returned PSBT input ${inputIndex}: P2WPKH pubkey does not hash to the ` +\n        `prevout's witness program.`,\n    );\n  }\n\n  // Strict-DER decode with defined-hashtype gate — the accept set of\n  // ecdsa::Signature::from_slice / EcdsaSighashType::from_standard\n  // (client.rs:978-980) — then SIGHASH_ALL exactly (client.rs:981-987).\n  let decoded: { signature: Buffer; hashType: number };\n  try {\n    decoded = bscript.signature.decode(Buffer.from(encodedSignature));\n  } catch (e) {\n    throw new Error(\n      `Returned PSBT input ${inputIndex}: P2WPKH signature is not DER with a ` +\n        `defined sighash byte: ${e instanceof Error ? e.message : String(e)}`,\n    );\n  }\n  // decode tolerates non-minimal integers (bip66.js never bounds lenR/lenS at 33;\n  // fromDER truncates, script_signature.js:29-35) that libsecp's strict consensus\n  // parse rejects (secp256k1-sys ecdsa_impl.h:127-136) — require the unique\n  // minimal encoding by re-encoding and byte-comparing.\n  if (\n    !bscript.signature\n      .encode(decoded.signature, decoded.hashType)\n      .equals(Buffer.from(encodedSignature))\n  ) {\n    throw new Error(\n      `Returned PSBT input ${inputIndex}: P2WPKH signature is not canonical DER.`,\n    );\n  }\n  if (decoded.hashType !== Transaction.SIGHASH_ALL) {\n    throw new Error(\n      `Returned PSBT input ${inputIndex}: P2WPKH signature has sighash type ` +\n        `0x${decoded.hashType.toString(16)} (expected SIGHASH_ALL).`,\n    );\n  }\n\n  // BIP-143 sighash over the REQUESTED prevout value with the standard\n  // P2WPKH scriptCode built from the witness program (client.rs:988-991;\n  // scriptCode template per bitcoinjs-lib's own P2WPKH signer,\n  // `src/psbt.js:1245-1255`).\n  const scriptCode = payments.p2pkh({ hash: Buffer.from(program) }).output;\n  if (!scriptCode) {\n    throw new Error(\n      `Returned PSBT input ${inputIndex}: could not build the P2WPKH scriptCode.`,\n    );\n  }\n  const tx = Transaction.fromBuffer(psbt.data.globalMap.unsignedTx.toBuffer());\n  const sighash = tx.hashForWitnessV0(\n    inputIndex,\n    scriptCode,\n    prevout.value,\n    decoded.hashType,\n  );\n\n  // strict=true rejects high-S, as libsecp256k1's verify_ecdsa does\n  // (client.rs:992-999; secp256k1 crate `ecdsa/mod.rs:194`). ecc.verify\n  // throws on out-of-range r/s — that is a failed verification here.\n  let verifies = false;\n  try {\n    verifies = ecc.verify(sighash, pubkey, decoded.signature, true);\n  } catch {\n    verifies = false;\n  }\n  if (!verifies) {\n    throw new Error(\n      `P2WPKH signature for input ${inputIndex} does not verify against the ` +\n        `requested PSBT's prevout. The wallet may have signed a different ` +\n        `transaction or key.`,\n    );\n  }\n}\n","/**\n * Far-side verification of Taproot KEY-PATH Schnorr signatures a wallet\n * returned, over the PSBT we requested (trusted prevouts) — the key-path twin\n * of `assertScriptPathSchnorrSignature`. Reference: btc-vault\n * `crates/btc-wallet-remote/src/client.rs check_signatures_valid` (output key taken\n * from the prevout scriptPubKey, all prevouts committed). The wallet's\n * success/finalization is never trusted on its own (CLAUDE.md §8).\n * `assertReturnedKeyPathSignatures` additionally dispatches P2WPKH-funded\n * inputs to `verifyP2wpkhEcdsaSignature` (client.rs's\n * `verify_finalized_p2wpkh_spend` sibling), so a Native SegWit software\n * wallet's signatures no longer pass through unchecked.\n *\n * Why verify against the *requested* PSBT: `assertPsbtUnsignedTxMatches` pins\n * the unsigned transaction but deliberately skips per-input metadata, so a\n * wallet could rewrite `witnessUtxo` in its response and make a wrong-message\n * signature self-validate. Prevout scripts and values therefore come from the\n * PSBT we built; only the signature bytes come from the wallet.\n *\n * @module tbv/core/primitives/psbt/verifyKeyPathSchnorrSignature\n */\n\nimport * as ecc from \"@bitcoin-js/tiny-secp256k1-asmjs\";\nimport { Psbt, Transaction } from \"bitcoinjs-lib\";\n\nimport { Buffer } from \"buffer\";\n\nimport { decodeWitnessStack } from \"../../utils/witness/witnessStack\";\nimport { hexToUint8Array, stripHexPrefix } from \"../utils/bitcoin\";\nimport {\n  assertReturnedP2wpkhSignature,\n  isP2wpkhScript,\n} from \"./verifyP2wpkhEcdsaSignature\";\n\nconst SCHNORR_SIG_BYTES = 64;\nconst SIGHASH_DEFAULT = Transaction.SIGHASH_DEFAULT; // 0x00\nconst SIGHASH_ALL = Transaction.SIGHASH_ALL; // 0x01\n\n// P2TR scriptPubKey is exactly `OP_1 OP_PUSHBYTES_32 <32-byte output key>`.\nconst P2TR_SCRIPT_LEN = 34;\nconst OP_1 = 0x51;\nconst OP_PUSHBYTES_32 = 0x20;\nconst P2TR_OUTPUT_KEY_OFFSET = 2;\n\nfunction isP2trScript(script: Uint8Array | undefined): script is Uint8Array {\n  return (\n    script !== undefined &&\n    script.length === P2TR_SCRIPT_LEN &&\n    script[0] === OP_1 &&\n    script[1] === OP_PUSHBYTES_32\n  );\n}\n\n/** BIP-341: 64 bytes ⇒ SIGHASH_DEFAULT; 65 bytes ⇒ the trailing byte is the hash type (we accept ALL only). */\nfunction splitHashType(\n  sig: Uint8Array,\n  inputIndex: number,\n): { signature: Uint8Array; hashType: number } {\n  if (sig.length === SCHNORR_SIG_BYTES) {\n    return { signature: sig, hashType: SIGHASH_DEFAULT };\n  }\n  if (\n    sig.length === SCHNORR_SIG_BYTES + 1 &&\n    sig[SCHNORR_SIG_BYTES] === SIGHASH_ALL\n  ) {\n    return {\n      signature: sig.subarray(0, SCHNORR_SIG_BYTES),\n      hashType: SIGHASH_ALL,\n    };\n  }\n  throw new Error(\n    `Key-path signature for input ${inputIndex} must be 64 bytes (SIGHASH_DEFAULT) or ` +\n      `65 bytes ending in 0x01 (SIGHASH_ALL), got ${sig.length}.`,\n  );\n}\n\nexport interface AssertKeyPathSchnorrSignatureParams {\n  /** Hex of the PSBT we built and sent (trusted prevout scripts/values). NOT the wallet's. */\n  requestedPsbtHex: string;\n  /** 64- or 65-byte signature, hex. */\n  signatureHex: string;\n  /** Index of the input the signature is for. */\n  inputIndex: number;\n}\n\n/**\n * Assert that `signatureHex` is a valid BIP-340 Schnorr signature over the\n * Taproot key-path sighash of `requestedPsbtHex` input `inputIndex`, under the\n * tweaked output key taken from that input's prevout scriptPubKey.\n *\n * @throws If the input is not a key-path P2TR spend, the requested PSBT lacks\n *         the prevout data needed to recompute the sighash, or the signature\n *         does not verify.\n */\nexport function assertKeyPathSchnorrSignature(\n  params: AssertKeyPathSchnorrSignatureParams,\n): void {\n  const { requestedPsbtHex, signatureHex, inputIndex } = params;\n\n  const psbt = Psbt.fromHex(requestedPsbtHex);\n\n  if (inputIndex < 0 || inputIndex >= psbt.data.inputs.length) {\n    throw new Error(\n      `Input index ${inputIndex} out of range (${psbt.data.inputs.length} inputs).`,\n    );\n  }\n\n  if (!isKeyPathEligible(psbt.data.inputs[inputIndex])) {\n    throw new Error(\n      `Input ${inputIndex} of the requested PSBT is not a key-path P2TR input.`,\n    );\n  }\n\n  // Taproot's sighash commits to every input's prevout (script + value), so all\n  // inputs must carry a witnessUtxo. A missing one is a build error, not a\n  // value we can default — fail loudly.\n  const prevOutScripts: Buffer[] = [];\n  const values: number[] = [];\n  for (let i = 0; i < psbt.data.inputs.length; i++) {\n    const prevout = psbt.data.inputs[i].witnessUtxo;\n    if (!prevout) {\n      throw new Error(\n        `Cannot verify signature: input ${i} of the requested PSBT has no witnessUtxo ` +\n          `(required to recompute the Taproot sighash).`,\n      );\n    }\n    prevOutScripts.push(prevout.script);\n    values.push(prevout.value);\n  }\n\n  const { signature, hashType } = splitHashType(\n    hexToUint8Array(stripHexPrefix(signatureHex)),\n    inputIndex,\n  );\n\n  const tx = Transaction.fromBuffer(psbt.data.globalMap.unsignedTx.toBuffer());\n  const sighash = tx.hashForWitnessV1(\n    inputIndex,\n    prevOutScripts,\n    values,\n    hashType,\n  );\n\n  // Key-path signatures verify against the TWEAKED output key = the prevout's\n  // witness program.\n  const outputKey = prevOutScripts[inputIndex].subarray(P2TR_OUTPUT_KEY_OFFSET);\n\n  if (!ecc.verifySchnorr(sighash, outputKey, signature)) {\n    throw new Error(\n      `Key-path Schnorr signature for input ${inputIndex} does not verify against the ` +\n        `requested PSBT's prevout (output key ${Buffer.from(outputKey).toString(\"hex\")}). ` +\n        `The wallet may have signed a different transaction or key.`,\n    );\n  }\n}\n\n/**\n * A key-path P2TR input: an internal key, no script-path material, and a\n * taproot prevout. Script-path inputs are the script-path verifier's job.\n */\nfunction isKeyPathEligible(input: {\n  tapInternalKey?: Uint8Array;\n  tapLeafScript?: unknown;\n  tapMerkleRoot?: Uint8Array;\n  witnessUtxo?: { script: Uint8Array };\n}): boolean {\n  return (\n    input.tapInternalKey !== undefined &&\n    input.tapLeafScript === undefined &&\n    input.tapMerkleRoot === undefined &&\n    isP2trScript(input.witnessUtxo?.script)\n  );\n}\n\n/**\n * The lone stack item of a finalized key-path witness. An annex would add a\n * second item, but Bitcoin Core rejects annexes as nonstandard\n * (`src/policy/policy.cpp:327-329`), so such a spend could never broadcast.\n */\nfunction singleWitnessItem(\n  finalScriptWitness: Uint8Array,\n  inputIndex: number,\n): Uint8Array {\n  const items = decodeWitnessStack(finalScriptWitness, \"finalScriptWitness\");\n  if (items.length !== 1) {\n    throw new Error(\n      `Returned PSBT input ${inputIndex}: a finalized key-path witness must have ` +\n        `exactly one item, got ${items.length}.`,\n    );\n  }\n  return items[0];\n}\n\nfunction bytesEqual(a: Uint8Array, b: Uint8Array): boolean {\n  return a.length === b.length && a.every((byte, i) => byte === b[i]);\n}\n\nexport interface AssertReturnedKeyPathSignaturesParams {\n  /** PSBT we built locally and asked the wallet to sign. */\n  requestedPsbtHex: string;\n  /** PSBT the wallet returned after signing. */\n  returnedPsbtHex: string;\n}\n\n/**\n * Verify every key-path-eligible and P2WPKH input of the REQUESTED PSBT\n * against what the wallet RETURNED. Key-path: `tapKeySig`, or the single\n * finalized witness item for wallets that auto-finalize — and when both are\n * present they must be the same bytes. P2WPKH: `partialSig`, or the finalized\n * 2-item witness, verified as ECDSA over the BIP-143 sighash\n * ({@link assertReturnedP2wpkhSignature}); a failure throws but the input is\n * NOT counted. Any other input type (script-path, P2WSH, ...) throws — no\n * verifier here covers it, so it cannot be treated as verified.\n *\n * @returns How many inputs were verified KEY-PATH. A caller that knows every\n *          input is taproot key-path (e.g. an approval wallet) must assert\n *          this equals its input count — P2WPKH inputs never count toward it,\n *          so that gate stays exact.\n * @throws If the input counts differ, an input is neither key-path P2TR nor\n *         P2WPKH, an eligible input carries no signature, a finalized witness\n *         disagrees with its `tapKeySig`/`partialSig`, or any signature does\n *         not verify.\n */\nexport function assertReturnedKeyPathSignatures(\n  params: AssertReturnedKeyPathSignaturesParams,\n): number {\n  const { requestedPsbtHex, returnedPsbtHex } = params;\n\n  const requested = Psbt.fromHex(requestedPsbtHex);\n  const returned = Psbt.fromHex(returnedPsbtHex);\n\n  if (returned.data.inputs.length !== requested.data.inputs.length) {\n    throw new Error(\n      `Returned PSBT input count ${returned.data.inputs.length} differs from the ` +\n        `requested ${requested.data.inputs.length}.`,\n    );\n  }\n\n  let verified = 0;\n  requested.data.inputs.forEach((input, inputIndex) => {\n    const returnedInput = returned.data.inputs[inputIndex];\n\n    if (!isKeyPathEligible(input)) {\n      // Native SegWit funding inputs get the ECDSA check.\n      if (isP2wpkhScript(input.witnessUtxo?.script)) {\n        assertReturnedP2wpkhSignature({\n          requestedPsbtHex,\n          returnedInput,\n          inputIndex,\n        });\n        return;\n      }\n      // No verifier exists for any other type — fail closed like btc-vault's\n      // check_signatures_valid rather than silently reporting it checked.\n      throw new Error(\n        `Input ${inputIndex} of the requested PSBT is neither key-path P2TR ` +\n          `nor P2WPKH; refusing to treat it as verified.`,\n      );\n    }\n    verified++;\n\n    const tapKeySig = returnedInput.tapKeySig;\n    const witnessSig = returnedInput.finalScriptWitness\n      ? singleWitnessItem(returnedInput.finalScriptWitness, inputIndex)\n      : undefined;\n\n    // Both fields can be present, and the consumers broadcast the WITNESS\n    // bytes — so the two must agree, not just one of them verify. Matches\n    // btc-vault `crates/btc-wallet-remote/src/client.rs:1053-1072,1102-1121`,\n    // which checks each independently.\n    if (tapKeySig && witnessSig && !bytesEqual(tapKeySig, witnessSig)) {\n      throw new Error(\n        `Returned PSBT input ${inputIndex} finalized witness does not match its tapKeySig.`,\n      );\n    }\n\n    const sig = tapKeySig ?? witnessSig;\n    if (!sig) {\n      throw new Error(\n        `Returned PSBT input ${inputIndex} carries no key-path signature ` +\n          `(no tapKeySig, not finalized).`,\n      );\n    }\n\n    assertKeyPathSchnorrSignature({\n      requestedPsbtHex,\n      signatureHex: Buffer.from(sig).toString(\"hex\"),\n      inputIndex,\n    });\n  });\n\n  return verified;\n}\n"],"names":["buildPeginInputPsbt","params","peginTxHex","stripHexPrefix","fundedPrePeginTxHex","htlcConnector","getPrePeginHtlcConnectorInfo","peginTx","Transaction","prePeginTx","peginInput","prePeginTxid","peginInputTxid","uint8ArrayToHex","htlcOutput","hashlockScript","hexToUint8Array","hashlockControlBlock","assertEccInitialized","htlcTaptree","payments","Buffer","tapInternalPubkey","TAPSCRIPT_LEAF_VERSION","_a","psbt","Psbt","output","extractPeginInputSignature","signedPsbtHex","depositorPubkey","input","depositorPubkeyBytes","sigEntry","extractSchnorrSig","finalizePeginInputPsbt","e","inp","sig","COMPACT_SIZE_UINT16_PREFIX","COMPACT_SIZE_UINT32_PREFIX","COMPACT_SIZE_UINT16_BYTES","COMPACT_SIZE_UINT32_BYTES","COMPACT_SIZE_UINT16_MIN_VALUE","COMPACT_SIZE_UINT32_MIN_VALUE","decodeWitnessStack","witness","subject","offset","readCompactSize","first","value","count","items","i","len","P2WPKH_SCRIPT_LEN","OP_0","OP_PUSHBYTES_20","P2WPKH_PROGRAM_START","COMPRESSED_PUBKEY_BYTES","P2WPKH_WITNESS_ITEMS","isP2wpkhScript","script","bytesEqual","a","b","byte","decodeP2wpkhWitness","finalScriptWitness","inputIndex","assertReturnedP2wpkhSignature","requestedPsbtHex","returnedInput","partials","partial","material","assertP2wpkhEcdsaSignature","encodedSignature","pubkey","prevout","ecc","program","bcrypto","decoded","bscript","scriptCode","sighash","verifies","SCHNORR_SIG_BYTES","SIGHASH_DEFAULT","SIGHASH_ALL","P2TR_SCRIPT_LEN","OP_1","OP_PUSHBYTES_32","P2TR_OUTPUT_KEY_OFFSET","isP2trScript","splitHashType","assertKeyPathSchnorrSignature","signatureHex","isKeyPathEligible","prevOutScripts","values","signature","hashType","outputKey","singleWitnessItem","assertReturnedKeyPathSignatures","returnedPsbtHex","requested","returned","verified","tapKeySig","witnessSig"],"mappings":"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"}