smplx-std 0.0.5

A blazingly-fast, ux-first simplicity development framework
Documentation
/* 
 * Extends `bytes32_tr_storage` using `array_fold` for larger buffers.
 * Optimized for small, fixed-size states where linear hashing is more efficient
 * than Merkle Trees. By avoiding proof overhead like sibling hashes, we reduce 
 * witness size and simplify contract logic for small N.
 * This approach is particularly advantageous when updating all slots within every transaction.
 */

fn hash_array_tr_storage(elem: u256, ctx: Ctx8) -> Ctx8 {
    jet::sha_256_ctx_8_add_32(ctx, elem)
}

fn hash_array_tr_storage_with_update(elem: u256, triplet: (Ctx8, u16, u16)) -> (Ctx8, u16, u16) {
    let (ctx, i, changed_index): (Ctx8, u16, u16) = triplet;

    match jet::eq_16(i, changed_index) {
        true => {
            let (_, val): (bool, u16) = jet::increment_16(i);

            // There may be arbitrary logic here
            let (state1, state2, state3, state4): (u64, u64, u64, u64) = <u256>::into(elem);
            let new_state4: u64 = 20;

            let new_state: u256 = <(u64, u64, u64, u64)>::into((state1, state2, state3, new_state4));
            (
                jet::sha_256_ctx_8_add_32(ctx, new_state),
                val,
                changed_index,
            )
        },
        false => {
            let (_, val): (bool, u16) = jet::increment_16(i);
            (
                jet::sha_256_ctx_8_add_32(ctx, elem),
                val,
                changed_index,
            )
        }
    }
}

fn script_hash_for_input_script(state: [u256; 3], changed_index: Option<u16>) -> u256 {
    let tap_leaf: u256 = jet::tapleaf_hash();
    let ctx: Ctx8 = jet::tapdata_init();

    let (ctx, _, _): (Ctx8, u16, u16) = match changed_index {
        Some(ind: u16) => {
            array_fold::<hash_array_tr_storage_with_update, 3>(state, (ctx, 0, ind))
        },
        None => {
            (array_fold::<hash_array_tr_storage, 3>(state, ctx), 0, 0)
        }
    };

    let computed: u256 = jet::sha_256_ctx_8_finalize(ctx);
    let tap_node: u256 = jet::build_tapbranch(tap_leaf, computed);

    let bip0341_key: u256 = 0x50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0;
    let tweaked_key: u256 = jet::build_taptweak(bip0341_key, tap_node);
    
    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: [u256; 3] = witness::STATE;

    // Assert that the input is correct, i.e. "load".
    assert!(jet::eq_256(
        script_hash_for_input_script(state, None),
        unwrap(jet::input_script_hash(jet::current_index()))
    ));

    // Assert that the output is correct, i.e. "store".
    assert!(jet::eq_256(
        script_hash_for_input_script(state, Some(witness::CHANGED_INDEX)),
        unwrap(jet::output_script_hash(jet::current_index()))
    ));
}