{"version":3,"file":"noPayout-Ox27Td9x.cjs","sources":["../src/tbv/core/primitives/psbt/refund.ts","../src/tbv/core/primitives/psbt/noPayout.ts"],"sourcesContent":["/**\n * Refund PSBT Builder Primitive\n *\n * Builds an unsigned refund PSBT for a depositor to reclaim BTC from\n * a timed-out Pre-PegIn HTLC output via the refund script (leaf 1).\n *\n * The refund script enforces a CSV timelock (timelockRefund blocks) and\n * requires only the depositor's Schnorr signature — no vault provider or\n * keeper involvement.\n *\n * @module primitives/psbt/refund\n */\n\nimport {\n  assertPositiveBigintArray,\n  getPrePeginHtlcConnectorInfo,\n  initWasm,\n  tapInternalPubkey,\n  WasmPrePeginTx,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction } from \"bitcoinjs-lib\";\n\nimport {\n  TAPSCRIPT_LEAF_VERSION,\n  deriveBip86ScriptPubKeyHex,\n  hexToUint8Array,\n  stripHexPrefix,\n  uint8ArrayToHex,\n} from \"../utils/bitcoin\";\nimport { normalizeAuthAnchorHash, type PrePeginParams } from \"./pegin\";\n\n/**\n * Parameters for building a refund PSBT\n */\nexport interface BuildRefundPsbtParams {\n  /** Same PrePeginParams used when the original Pre-PegIn tx was created */\n  prePeginParams: PrePeginParams;\n  /** Funded Pre-PegIn transaction hex (the tx whose HTLC output is being refunded) */\n  fundedPrePeginTxHex: string;\n  /** Index of the HTLC output in the Pre-PegIn transaction */\n  htlcVout: number;\n  /** Transaction fee in satoshis for the refund transaction */\n  refundFee: bigint;\n  /** SHA256 hash commitment for the HTLC (64 hex chars, no 0x prefix) */\n  hashlock: string;\n}\n\n/**\n * Result of building a refund PSBT\n */\nexport interface BuildRefundPsbtResult {\n  /** PSBT hex ready for depositor signing */\n  psbtHex: string;\n}\n\n/**\n * Build a PSBT for signing the refund transaction.\n *\n * The refund transaction spends the Pre-PegIn HTLC output via leaf 1\n * (the refund script: `<timelockRefund> CSV DROP <depositorPubkey> CHECKSIG`).\n * The PSBT includes the tapLeafScript entry so the depositor's wallet can\n * sign using Taproot script-path spending.\n *\n * The input's sequence is set to `timelockRefund` by the WASM, enforcing\n * the Bitcoin CSV timelock. The refund broadcast will be rejected by the\n * network if the timelock has not yet expired.\n *\n * @param params - Refund PSBT parameters\n * @returns PSBT hex for depositor signing\n * @throws If the HTLC output at htlcVout is not found\n * @throws If the refund transaction does not have exactly 1 input\n */\nexport async function buildRefundPsbt(\n  params: BuildRefundPsbtParams,\n): Promise<BuildRefundPsbtResult> {\n  await initWasm();\n\n  const { prePeginParams, fundedPrePeginTxHex, htlcVout, refundFee, hashlock } =\n    params;\n\n  // The 14th positional arg `auth_anchor_hash` is `Option<String>` in\n  // the Rust WASM constructor (the 9th arg `min_pegin_fee_rate` requires\n  // the two-rate constructor from btc-vault #1930). Production peg-ins\n  // (PeginManager) always commit an OP_RETURN <PUSH32 SHA256(authAnchor)>\n  // output at `vout = hashlocks.length`; the unfunded template must\n  // include it so `fromFundedTransaction` aligns with the funded tx.\n  // Normalize identically to the peg-in primitives (`0x` strip,\n  // lowercase, length/charset validation) so a direct primitive caller\n  // reusing successful peg-in params doesn't hand unnormalized bytes to\n  // WASM. Pass `undefined` for legacy non-auth-anchored Pre-PegIns.\n  const normalizedAuthAnchorHash = normalizeAuthAnchorHash(\n    prePeginParams.authAnchorHash,\n  );\n  // Reconstruct the template under the same graph version the Pre-PegIn\n  // was originally built with (the vault's stamped vaultCoreVersion).\n  const unfundedTx = new WasmPrePeginTx(\n    prePeginParams.vaultCoreVersion,\n    prePeginParams.depositorPubkey,\n    prePeginParams.vaultProviderPubkey,\n    prePeginParams.vaultKeeperPubkeys,\n    prePeginParams.universalChallengerPubkeys,\n    [...prePeginParams.hashlocks],\n    new BigUint64Array(\n      assertPositiveBigintArray(prePeginParams.pegInAmounts, \"pegInAmounts\"),\n    ),\n    prePeginParams.timelockRefund,\n    prePeginParams.feeRate,\n    prePeginParams.minPeginFeeRate,\n    prePeginParams.numLocalChallengers,\n    prePeginParams.councilQuorum,\n    prePeginParams.councilSize,\n    prePeginParams.network,\n    normalizedAuthAnchorHash,\n  );\n\n  let fundedTx: WasmPrePeginTx | null = null;\n  try {\n    // Cross-check the reconstructed unfunded template against the funded\n    // transaction: the WASM template's HTLC scriptPubKey at `htlcVout`\n    // must equal the bytes the funded tx carries at the same output.\n    // If they disagree, the template was reconstructed from the wrong\n    // (hashlocks, amounts) vector — signing it would produce a refund\n    // that does not spend the on-chain HTLC the depositor expects.\n    // This is the explicit invariant the audit recommends: never sign a\n    // refund whose template doesn't match the on-chain output bytes.\n    const expectedHtlcScriptPubKey = unfundedTx\n      .getHtlcScriptPubKey(htlcVout)\n      .toLowerCase();\n    // The reconstructed template's HTLC output value at `htlcVout`,\n    // sized by WASM from the supplied `pegInAmounts` via the protocol\n    // formula `htlcValue = peginAmount + depositorClaimValue + minPeginFee`.\n    // Captured before `fromFundedTransaction` to bind it to the value the\n    // funded tx actually carries (see the cross-check below).\n    const expectedHtlcValue = unfundedTx.getHtlcValue(htlcVout);\n\n    fundedTx = unfundedTx.fromFundedTransaction(fundedPrePeginTxHex);\n\n    const refundTxHex = fundedTx.buildRefundTx(refundFee, htlcVout);\n\n    const htlcConnector = await getPrePeginHtlcConnectorInfo({\n      txGraphVersion: prePeginParams.vaultCoreVersion,\n      depositorPubkey: prePeginParams.depositorPubkey,\n      vaultProviderPubkey: prePeginParams.vaultProviderPubkey,\n      vaultKeeperPubkeys: prePeginParams.vaultKeeperPubkeys,\n      universalChallengerPubkeys: prePeginParams.universalChallengerPubkeys,\n      hashlock,\n      timelockRefund: prePeginParams.timelockRefund,\n      network: prePeginParams.network,\n    });\n\n    const cleanPrePeginHex = fundedPrePeginTxHex.startsWith(\"0x\")\n      ? fundedPrePeginTxHex.slice(2)\n      : fundedPrePeginTxHex;\n    const prePeginTx = Transaction.fromHex(cleanPrePeginHex);\n\n    const htlcOutput = prePeginTx.outs[htlcVout];\n    if (!htlcOutput) {\n      throw new Error(\n        `HTLC output at vout ${htlcVout} not found in funded Pre-PegIn tx ` +\n          `(tx has ${prePeginTx.outs.length} outputs)`,\n      );\n    }\n\n    const actualHtlcScriptPubKey = uint8ArrayToHex(\n      new Uint8Array(htlcOutput.script),\n    ).toLowerCase();\n    if (actualHtlcScriptPubKey !== expectedHtlcScriptPubKey) {\n      throw new Error(\n        `HTLC scriptPubKey mismatch at vout ${htlcVout}: reconstructed ` +\n          `template expects ${expectedHtlcScriptPubKey}, funded tx carries ` +\n          `${actualHtlcScriptPubKey}. Refund refused — the (hashlocks, ` +\n          `pegInAmounts) vector does not match the on-chain commitment.`,\n      );\n    }\n\n    // Value cross-check (mirrors the script check above): the template's\n    // HTLC value — derived by WASM from `pegInAmounts` via the protocol\n    // formula — must equal the value the funded tx pays at this output.\n    // A caller that hands the full HTLC output value (or any wrong amount)\n    // as `pegInAmounts` would inflate the template value and trip this\n    // guard, rather than silently signing a refund built from a template\n    // that disagrees with the on-chain commitment.\n    const actualHtlcValue = BigInt(htlcOutput.value);\n    if (actualHtlcValue !== expectedHtlcValue) {\n      throw new Error(\n        `HTLC value mismatch at vout ${htlcVout}: reconstructed template ` +\n          `expects ${expectedHtlcValue} sat, funded tx carries ` +\n          `${actualHtlcValue} sat. Refund refused — the pegInAmounts vector ` +\n          `does not match the on-chain commitment.`,\n      );\n    }\n\n    const refundTx = Transaction.fromHex(refundTxHex);\n\n    if (refundTx.ins.length !== 1) {\n      throw new Error(\n        `Refund transaction must have exactly 1 input, got ${refundTx.ins.length}`,\n      );\n    }\n\n    const refundInput = refundTx.ins[0];\n\n    // Verify the refund input spends the correct Pre-PegIn HTLC output\n    const prePeginTxid = prePeginTx.getId();\n    const refundInputTxid = uint8ArrayToHex(\n      new Uint8Array(refundInput.hash).slice().reverse(),\n    );\n    if (refundInputTxid !== prePeginTxid) {\n      throw new Error(\n        `Refund input does not reference the Pre-PegIn transaction. ` +\n          `Expected ${prePeginTxid}, got ${refundInputTxid}`,\n      );\n    }\n    if (refundInput.index !== htlcVout) {\n      throw new Error(\n        `Refund input index ${refundInput.index} does not match expected htlcVout ${htlcVout}`,\n      );\n    }\n\n    const psbt = new Psbt();\n    psbt.setVersion(refundTx.version);\n    psbt.setLocktime(refundTx.locktime);\n\n    psbt.addInput({\n      hash: refundInput.hash,\n      index: refundInput.index,\n      sequence: refundInput.sequence,\n      witnessUtxo: {\n        script: htlcOutput.script,\n        value: htlcOutput.value,\n      },\n      tapLeafScript: [\n        {\n          leafVersion: TAPSCRIPT_LEAF_VERSION,\n          script: Buffer.from(hexToUint8Array(htlcConnector.refundScript)),\n          controlBlock: Buffer.from(\n            hexToUint8Array(htlcConnector.refundControlBlock),\n          ),\n        },\n      ],\n      tapInternalKey: Buffer.from(tapInternalPubkey),\n    });\n\n    // Output side: pin the single refund output to the depositor's own\n    // BIP-86 P2TR address, mirroring the input-side pinning above. WASM\n    // builds the refund output from the refund leaf's depositor key, so a\n    // correct template always pays exactly one output back to the depositor.\n    // Asserting it here means a malformed template (or a tampered WASM)\n    // cannot redirect the reclaimed funds to a script the depositor does\n    // not control.\n    if (refundTx.outs.length !== 1) {\n      throw new Error(\n        `Refund transaction must have exactly 1 output, got ${refundTx.outs.length}`,\n      );\n    }\n    const refundOutput = refundTx.outs[0];\n    const expectedDepositorScriptPubKey = stripHexPrefix(\n      deriveBip86ScriptPubKeyHex(prePeginParams.depositorPubkey),\n    ).toLowerCase();\n    const actualRefundOutputScriptPubKey = uint8ArrayToHex(\n      new Uint8Array(refundOutput.script),\n    ).toLowerCase();\n    if (actualRefundOutputScriptPubKey !== expectedDepositorScriptPubKey) {\n      throw new Error(\n        `Refund output scriptPubKey ${actualRefundOutputScriptPubKey} does not ` +\n          `match the depositor's BIP-86 address ${expectedDepositorScriptPubKey}. ` +\n          `Refund refused — the reclaimed funds would not return to the depositor.`,\n      );\n    }\n\n    // Value: the single refund output must return the full HTLC value minus\n    // exactly the requested fee. The refund is 1-in/1-out (asserted above), so\n    // a value below `htlcValue - refundFee` means WASM applied a larger fee\n    // than requested — the difference would be burned as miner fee. Pin it so\n    // the depositor reclaims the expected amount, not a silently reduced one.\n    const expectedRefundOutputValue = actualHtlcValue - refundFee;\n    if (BigInt(refundOutput.value) !== expectedRefundOutputValue) {\n      throw new Error(\n        `Refund output value ${BigInt(refundOutput.value)} sat does not equal ` +\n          `the HTLC value ${actualHtlcValue} sat minus the requested fee ` +\n          `${refundFee} sat (expected ${expectedRefundOutputValue} sat). ` +\n          `Refund refused — the reclaimed amount would be burned as excess fee.`,\n      );\n    }\n\n    psbt.addOutput({\n      script: refundOutput.script,\n      value: refundOutput.value,\n    });\n\n    return { psbtHex: psbt.toHex() };\n  } finally {\n    fundedTx?.free();\n    unfundedTx.free();\n  }\n}\n","/**\n * NoPayout PSBT Builder\n *\n * Builds unsigned PSBTs for the depositor's NoPayout transaction\n * (depositor-as-claimer path, per challenger). The depositor signs input 0\n * using the NoPayout taproot script from WasmAssertPayoutNoPayoutConnector.\n *\n * @module primitives/psbt/noPayout\n * @see btc-vault crates/vault/docs/btc-transactions-spec.md — Assert output 0 NoPayout connector\n */\n\nimport {\n  type AssertPayoutNoPayoutConnectorParams,\n  type Network,\n  getAssertNoPayoutScriptInfo,\n  tapInternalPubkey,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction, payments } from \"bitcoinjs-lib\";\n\nimport {\n  TAPSCRIPT_LEAF_VERSION,\n  getNetwork,\n  hexToUint8Array,\n  processPublicKeyToXOnly,\n  stripHexPrefix,\n} from \"../utils/bitcoin\";\n\n/**\n * Parameters for building a NoPayout PSBT\n */\nexport interface NoPayoutParams {\n  /** NoPayout transaction hex (unsigned) from VP */\n  noPayoutTxHex: string;\n  /** Challenger's x-only public key (hex encoded) */\n  challengerPubkey: string;\n  /** Prevouts for all inputs [{script_pubkey, value}] from VP */\n  prevouts: Array<{ script_pubkey: string; value: number }>;\n  /** Parameters for the Assert Payout/NoPayout connector */\n  connectorParams: AssertPayoutNoPayoutConnectorParams;\n}\n\n/**\n * Build unsigned NoPayout PSBT.\n *\n * The NoPayout transaction is specific to each challenger.\n * Input 0 is the one the depositor signs using the NoPayout taproot script path.\n *\n * @param params - NoPayout parameters\n * @returns Unsigned PSBT hex ready for signing\n */\nexport async function buildNoPayoutPsbt(\n  params: NoPayoutParams,\n): Promise<string> {\n  const noPayoutTxHex = stripHexPrefix(params.noPayoutTxHex);\n  const noPayoutTx = Transaction.fromHex(noPayoutTxHex);\n\n  // Get NoPayout script and control block for this challenger\n  const { noPayoutScript, noPayoutControlBlock } =\n    await getAssertNoPayoutScriptInfo(\n      params.connectorParams,\n      params.challengerPubkey,\n    );\n\n  const scriptBytes = hexToUint8Array(noPayoutScript);\n  const controlBlockBytes = hexToUint8Array(noPayoutControlBlock);\n\n  const psbt = new Psbt();\n  psbt.setVersion(noPayoutTx.version);\n  psbt.setLocktime(noPayoutTx.locktime);\n\n  // Add all inputs - depositor signs input 0 only\n  for (let i = 0; i < noPayoutTx.ins.length; i++) {\n    const input = noPayoutTx.ins[i];\n    const prevout = params.prevouts[i];\n\n    if (!prevout) {\n      throw new Error(`Missing prevout data for input ${i}`);\n    }\n\n    const inputData: Parameters<typeof psbt.addInput>[0] = {\n      hash: input.hash,\n      index: input.index,\n      sequence: input.sequence,\n      witnessUtxo: {\n        script: Buffer.from(hexToUint8Array(stripHexPrefix(prevout.script_pubkey))),\n        value: prevout.value,\n      },\n    };\n\n    // Input 0: depositor signs using taproot script path\n    if (i === 0) {\n      inputData.tapLeafScript = [\n        {\n          leafVersion: TAPSCRIPT_LEAF_VERSION,\n          script: Buffer.from(scriptBytes),\n          controlBlock: Buffer.from(controlBlockBytes),\n        },\n      ];\n      inputData.tapInternalKey = Buffer.from(tapInternalPubkey);\n    }\n\n    psbt.addInput(inputData);\n  }\n\n  // Add outputs\n  for (const output of noPayoutTx.outs) {\n    psbt.addOutput({\n      script: output.script,\n      value: output.value,\n    });\n  }\n\n  return psbt.toHex();\n}\n\n/**\n * Validate that a NoPayout transaction pays to the challenger via the\n * protocol-defined output structure: a single BIP-86 P2TR output derived from\n * the challenger's x-only pubkey.\n *\n * Mirrors the per-role payout output validation now inlined in\n * `buildPayoutPsbt` for the NoPayout path, where the sink is fixed by the\n * protocol rather than read from on-chain registration\n * (see `crates/vault/src/transactions/nopayout.rs::NoPayoutTx::new`).\n *\n * @param noPayoutTxHex - Raw NoPayout transaction hex\n * @param challengerPubkey - Challenger's x-only public key (hex)\n * @param network - Bitcoin network used to derive the P2TR scriptPubKey\n * @throws If the transaction does not have exactly one output\n * @throws If the single output's scriptPubKey does not equal the BIP-86 P2TR\n *         scriptPubKey for the challenger\n */\nexport function assertNoPayoutOutputMatchesChallenger(\n  noPayoutTxHex: string,\n  challengerPubkey: string,\n  network: Network,\n): void {\n  const tx = Transaction.fromHex(stripHexPrefix(noPayoutTxHex));\n\n  if (tx.outs.length !== 1) {\n    throw new Error(\n      `NoPayout transaction must have exactly 1 output, got ${tx.outs.length}`,\n    );\n  }\n\n  const xOnly = hexToUint8Array(processPublicKeyToXOnly(challengerPubkey));\n  const { output: expectedScript } = payments.p2tr({\n    internalPubkey: Buffer.from(xOnly),\n    network: getNetwork(network),\n  });\n  if (!expectedScript) {\n    throw new Error(\n      \"Failed to derive challenger BIP-86 P2TR scriptPubKey for NoPayout output validation\",\n    );\n  }\n\n  if (!tx.outs[0].script.equals(expectedScript)) {\n    throw new Error(\n      \"NoPayout transaction does not pay to the expected challenger BIP-86 P2TR address\",\n    );\n  }\n}\n"],"names":["buildRefundPsbt","params","initWasm","prePeginParams","fundedPrePeginTxHex","htlcVout","refundFee","hashlock","normalizedAuthAnchorHash","normalizeAuthAnchorHash","unfundedTx","WasmPrePeginTx","assertPositiveBigintArray","fundedTx","expectedHtlcScriptPubKey","expectedHtlcValue","refundTxHex","htlcConnector","getPrePeginHtlcConnectorInfo","cleanPrePeginHex","prePeginTx","Transaction","htlcOutput","actualHtlcScriptPubKey","uint8ArrayToHex","actualHtlcValue","refundTx","refundInput","prePeginTxid","refundInputTxid","psbt","Psbt","TAPSCRIPT_LEAF_VERSION","Buffer","hexToUint8Array","tapInternalPubkey","refundOutput","expectedDepositorScriptPubKey","stripHexPrefix","deriveBip86ScriptPubKeyHex","actualRefundOutputScriptPubKey","expectedRefundOutputValue","buildNoPayoutPsbt","noPayoutTxHex","noPayoutTx","noPayoutScript","noPayoutControlBlock","getAssertNoPayoutScriptInfo","scriptBytes","controlBlockBytes","i","input","prevout","inputData","output","assertNoPayoutOutputMatchesChallenger","challengerPubkey","network","tx","xOnly","processPublicKeyToXOnly","expectedScript","payments","getNetwork"],"mappings":"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"}