Taproot-native prevout binding via sighash preimage decomposition

Robin Linus’s How CTV+CSFS improves BitVM bridges raises a specific problem: how to bind inputA so it can only be spent together with a specific inputB. AJ Towns pointed out at /t/1591/8 that the original construction binds to scriptSig bytes rather than the outpoint itself. I posted a sketch at /t/1591/29 — using the sha_prevouts field of the sighash preimage as the binding anchor. This post gives the full witness layout, script reasoning.

What was done

The script (~196 bytes) hardcodes B’s outpoint (36 bytes of raw data — a transparent tweak factor). The witness supplies A’s outpoint. The script computes SHA256(witness_A_outpoint || B_outpoint_hardcoded) on stack and verifies it equals the sha_prevouts segment extracted from the chunked-witness preimage. Same-signature binding — one Schnorr signature satisfying both OP_CHECKSIG and OP_CHECKSIGFROMSTACK — ties the witness-supplied preimage to the actual transaction.

The witness is split along preimage field boundaries (each item < 80 bytes for standardness). The script uses OP_CAT to reassemble the 212-byte preimage, computes the TapSighash tagged hash on stack, then runs CSFS + CHECKSIG against the same 64-byte signature.

OP_CAT and OP_CHECKSIGFROMSTACK are both active on Bitcoin Inquisition signet, where the experiment runs.

Tested on Inquisition signet

Spending A + B (positive case) — confirmed:

Attack: spending A + C (substituting a different UTXO for B) — rejected by testmempoolaccept with Script failed an OP_EQUALVERIFY operation.

What this means in practice

For BitVM bridges: if B (the challenge anchor) is burned by a challenger, B is no longer in the UTXO set, and any transaction listing B as an input is invalid at the consensus level. The operator cannot withdraw A without proving B’s continued existence. More broadly, sighash preimage decomposition is a general method — sha_prevouts is one of several fields that can serve as a binding anchor.

Code: https://github.com/aaron-recompile/inquisition-experiments/blob/91ca2fcee64d81e066d5cb645ae84dbd7bb27870/experiments/exp_sighash_prevout_binding_chunked.py — happy to walk through the script step-by-step if useful.