{"version":3,"file":"challengeAssert-BrpC3-cQ.cjs","sources":["../src/tbv/core/primitives/psbt/challengeAssert.ts"],"sourcesContent":["/**\n * ChallengeAssert PSBT Builder\n *\n * Builds an unsigned PSBT for a ChallengeAssert transaction\n * (depositor-as-claimer path, per challenger). ChallengeAssert is split across\n * two single-input transactions — ChallengeAssertX (spends the challenger's\n * ConnectorX Assert output) and ChallengeAssertY (spends ConnectorY). This\n * builder handles one such transaction; the depositor signs every input, each\n * with its own taproot script derived from that input's connector params.\n *\n * @module primitives/psbt/challengeAssert\n * @see btc-vault crates/vault/docs/btc-transactions-spec.md — ChallengeAssertX / ChallengeAssertY\n */\n\nimport {\n  type ChallengeAssertConnectorParams,\n  getChallengeAssertScriptInfo,\n  tapInternalPubkey,\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  hexToUint8Array,\n  inputTxidHex,\n  stripHexPrefix,\n} from \"../utils/bitcoin\";\n\n/**\n * Parameters for building a ChallengeAssert PSBT\n */\nexport interface ChallengeAssertParams {\n  /** ChallengeAssert transaction hex (unsigned) */\n  challengeAssertTxHex: string;\n  /** Authoritative Assert transaction hex — every input must spend an Assert output */\n  assertTxHex: string;\n  /** Per-input connector params (one per input/segment, determines the taproot script) */\n  connectorParamsPerInput: ChallengeAssertConnectorParams[];\n}\n\n/**\n * Build unsigned ChallengeAssert PSBT.\n *\n * Each input has its own taproot script derived from its connector params; the\n * number of connector params must match the transaction's input count. The\n * depositor signs all inputs. Every prevout is derived from the authoritative\n * Assert transaction, never trusted from external input.\n *\n * @param params - ChallengeAssert parameters\n * @returns Unsigned PSBT hex ready for signing\n *\n * @throws If the number of connector params does not match the number of inputs\n * @throws If any input does not reference assertTxHex\n * @throws If any referenced Assert output is missing\n * @throws If two inputs reference the same Assert output index\n */\nexport async function buildChallengeAssertPsbt(\n  params: ChallengeAssertParams,\n): Promise<string> {\n  const challengeAssertTx = Transaction.fromHex(\n    stripHexPrefix(params.challengeAssertTxHex),\n  );\n  const assertTx = Transaction.fromHex(stripHexPrefix(params.assertTxHex));\n  const assertTxid = assertTx.getId();\n\n  if (params.connectorParamsPerInput.length !== challengeAssertTx.ins.length) {\n    throw new Error(\n      `Expected ${challengeAssertTx.ins.length} connector params, got ${params.connectorParamsPerInput.length}`,\n    );\n  }\n\n  const seenAssertOutputs = new Set<number>();\n  for (let i = 0; i < challengeAssertTx.ins.length; i++) {\n    const input = challengeAssertTx.ins[i];\n    const inputTxid = inputTxidHex(input);\n    if (inputTxid !== assertTxid) {\n      throw new Error(\n        `ChallengeAssert input ${i} must spend an Assert output. ` +\n          `Expected txid ${assertTxid}, got ${inputTxid}`,\n      );\n    }\n    if (!assertTx.outs[input.index]) {\n      throw new Error(\n        `Assert output ${input.index} not found for ChallengeAssert input ${i} (txid: ${assertTxid})`,\n      );\n    }\n    if (seenAssertOutputs.has(input.index)) {\n      throw new Error(\n        `ChallengeAssert input ${i} duplicates Assert output index ${input.index}`,\n      );\n    }\n    seenAssertOutputs.add(input.index);\n  }\n\n  const scriptInfos = await Promise.all(\n    params.connectorParamsPerInput.map((cp) => getChallengeAssertScriptInfo(cp)),\n  );\n\n  const psbt = new Psbt();\n  psbt.setVersion(challengeAssertTx.version);\n  psbt.setLocktime(challengeAssertTx.locktime);\n\n  for (let i = 0; i < challengeAssertTx.ins.length; i++) {\n    const input = challengeAssertTx.ins[i];\n    const assertPrevOut = assertTx.outs[input.index];\n\n    const { script, controlBlock } = scriptInfos[i];\n    const scriptBytes = hexToUint8Array(script);\n    const controlBlockBytes = hexToUint8Array(controlBlock);\n\n    psbt.addInput({\n      hash: input.hash,\n      index: input.index,\n      sequence: input.sequence,\n      witnessUtxo: {\n        script: assertPrevOut.script,\n        value: assertPrevOut.value,\n      },\n      tapLeafScript: [\n        {\n          leafVersion: TAPSCRIPT_LEAF_VERSION,\n          script: Buffer.from(scriptBytes),\n          controlBlock: Buffer.from(controlBlockBytes),\n        },\n      ],\n      tapInternalKey: Buffer.from(tapInternalPubkey),\n    });\n  }\n\n  for (const output of challengeAssertTx.outs) {\n    psbt.addOutput({\n      script: output.script,\n      value: output.value,\n    });\n  }\n\n  return psbt.toHex();\n}\n"],"names":["buildChallengeAssertPsbt","params","challengeAssertTx","Transaction","stripHexPrefix","assertTx","assertTxid","seenAssertOutputs","i","input","inputTxid","inputTxidHex","scriptInfos","cp","getChallengeAssertScriptInfo","psbt","Psbt","assertPrevOut","script","controlBlock","scriptBytes","hexToUint8Array","controlBlockBytes","TAPSCRIPT_LEAF_VERSION","Buffer","tapInternalPubkey","output"],"mappings":"yJAyDA,eAAsBA,EACpBC,EACiB,CACjB,MAAMC,EAAoBC,EAAAA,YAAY,QACpCC,EAAAA,eAAeH,EAAO,oBAAoB,CAAA,EAEtCI,EAAWF,EAAAA,YAAY,QAAQC,EAAAA,eAAeH,EAAO,WAAW,CAAC,EACjEK,EAAaD,EAAS,MAAA,EAE5B,GAAIJ,EAAO,wBAAwB,SAAWC,EAAkB,IAAI,OAClE,MAAM,IAAI,MACR,YAAYA,EAAkB,IAAI,MAAM,0BAA0BD,EAAO,wBAAwB,MAAM,EAAA,EAI3G,MAAMM,MAAwB,IAC9B,QAASC,EAAI,EAAGA,EAAIN,EAAkB,IAAI,OAAQM,IAAK,CACrD,MAAMC,EAAQP,EAAkB,IAAIM,CAAC,EAC/BE,EAAYC,EAAAA,aAAaF,CAAK,EACpC,GAAIC,IAAcJ,EAChB,MAAM,IAAI,MACR,yBAAyBE,CAAC,+CACPF,CAAU,SAASI,CAAS,EAAA,EAGnD,GAAI,CAACL,EAAS,KAAKI,EAAM,KAAK,EAC5B,MAAM,IAAI,MACR,iBAAiBA,EAAM,KAAK,wCAAwCD,CAAC,WAAWF,CAAU,GAAA,EAG9F,GAAIC,EAAkB,IAAIE,EAAM,KAAK,EACnC,MAAM,IAAI,MACR,yBAAyBD,CAAC,mCAAmCC,EAAM,KAAK,EAAA,EAG5EF,EAAkB,IAAIE,EAAM,KAAK,CACnC,CAEA,MAAMG,EAAc,MAAM,QAAQ,IAChCX,EAAO,wBAAwB,IAAKY,GAAOC,EAAAA,6BAA6BD,CAAE,CAAC,CAAA,EAGvEE,EAAO,IAAIC,OACjBD,EAAK,WAAWb,EAAkB,OAAO,EACzCa,EAAK,YAAYb,EAAkB,QAAQ,EAE3C,QAASM,EAAI,EAAGA,EAAIN,EAAkB,IAAI,OAAQM,IAAK,CACrD,MAAMC,EAAQP,EAAkB,IAAIM,CAAC,EAC/BS,EAAgBZ,EAAS,KAAKI,EAAM,KAAK,EAEzC,CAAE,OAAAS,EAAQ,aAAAC,GAAiBP,EAAYJ,CAAC,EACxCY,EAAcC,EAAAA,gBAAgBH,CAAM,EACpCI,EAAoBD,EAAAA,gBAAgBF,CAAY,EAEtDJ,EAAK,SAAS,CACZ,KAAMN,EAAM,KACZ,MAAOA,EAAM,MACb,SAAUA,EAAM,SAChB,YAAa,CACX,OAAQQ,EAAc,OACtB,MAAOA,EAAc,KAAA,EAEvB,cAAe,CACb,CACE,YAAaM,EAAAA,uBACb,OAAQC,EAAAA,OAAO,KAAKJ,CAAW,EAC/B,aAAcI,EAAAA,OAAO,KAAKF,CAAiB,CAAA,CAC7C,EAEF,eAAgBE,EAAAA,OAAO,KAAKC,EAAAA,iBAAiB,CAAA,CAC9C,CACH,CAEA,UAAWC,KAAUxB,EAAkB,KACrCa,EAAK,UAAU,CACb,OAAQW,EAAO,OACf,MAAOA,EAAO,KAAA,CACf,EAGH,OAAOX,EAAK,MAAA,CACd"}