/*
* Computes the "State Commitment" — the expected Script PubKey (address)
* for a specific state value.
*
* HOW IT WORKS:
* In Simplicity/Liquid, state is not stored in a dedicated database. Instead,
* it is verified via a "Commitment Scheme" inside the Taproot tree of the UTXO.
*
* This function reconstructs the Taproot structure to validate that the provided
* witness data (state_data) was indeed cryptographically embedded into the
* transaction output that is currently being spent.
*
* LOGIC FLOW:
* 1. Takes state_data (passed via witness at runtime).
* 2. Hashes it as a non-executable TapData leaf.
* 3. Combines it with the current program's CMR (tapleaf_hash).
* 4. Derives the tweaked_key (Internal Key + Merkle Root).
* 5. Returns the final SHA256 script hash (SegWit v1).
*
* USAGE:
* - In main, we verify: CalculatedHash(witness::STATE) == input_script_hash.
* - This assertion proves that the UTXO is "locked" not just by the code,
* but specifically by THIS instance of the state data.
*/
fn script_hash_for_input_script(state_data: u256) -> u256 {
// This is the bulk of our "compute state commitment" logic from above.
let tap_leaf: u256 = jet::tapleaf_hash();
let state_ctx1: Ctx8 = jet::tapdata_init();
let state_ctx2: Ctx8 = jet::sha_256_ctx_8_add_32(state_ctx1, state_data);
let state_leaf: u256 = jet::sha_256_ctx_8_finalize(state_ctx2);
let tap_node: u256 = jet::build_tapbranch(tap_leaf, state_leaf);
// Compute a taptweak using this.
let bip0341_key: u256 = 0x50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0;
let tweaked_key: u256 = jet::build_taptweak(bip0341_key, tap_node);
// Turn the taptweak into a script hash
let hash_ctx1: Ctx8 = jet::sha_256_ctx_8_init();
let hash_ctx2: Ctx8 = jet::sha_256_ctx_8_add_2(hash_ctx1, 0x5120); // Segwit v1, length 32
let hash_ctx3: Ctx8 = jet::sha_256_ctx_8_add_32(hash_ctx2, tweaked_key);
jet::sha_256_ctx_8_finalize(hash_ctx3)
}
fn main() {
let state_data: u256 = witness::STATE;
let (state1, state2, state3, state4): (u64, u64, u64, u64) = <u256>::into(state_data);
// Assert that the input is correct, i.e. "load".
assert!(jet::eq_256(
script_hash_for_input_script(state_data),
unwrap(jet::input_script_hash(jet::current_index()))
));
// Do a state update (and fail on 64-bit overflow even though we've got 192 other
// bits we could be using..)
let (carry, new_state4): (bool, u64) = jet::increment_64(state4);
assert!(jet::eq_1(<bool>::into(carry), 0));
let new_state: u256 = <(u64, u64, u64, u64)>::into((state1, state2, state3, new_state4));
// Assert that the output is correct, i.e. "store".
assert!(jet::eq_256(
script_hash_for_input_script(new_state),
unwrap(jet::output_script_hash(jet::current_index()))
));
}