openvm_continuations/circuit/subair/hash_slice/
trace.rs

1use openvm_circuit::arch::POSEIDON2_WIDTH;
2use openvm_recursion_circuit::utils::poseidon2_hash_slice_with_states;
3use openvm_stark_sdk::config::baby_bear_poseidon2::{DIGEST_SIZE, F};
4
5/// Given N element digests, compute the N−1 intermediate full permutation states
6/// and the final digest, matching the layout of [`HashSliceCtx`](super::HashSliceCtx).
7///
8/// If provided, the pre-permutation inputs for the first N−1 elements are appended
9/// to `poseidon2_permute_inputs`, and the pre-permutation input for the last element
10/// is appended to `poseidon2_compress_inputs`.
11pub fn hash_slice_trace(
12    elements: &[[F; DIGEST_SIZE]],
13    poseidon2_permute_inputs: Option<&mut Vec<[F; POSEIDON2_WIDTH]>>,
14    poseidon2_compress_inputs: Option<&mut Vec<[F; POSEIDON2_WIDTH]>>,
15) -> (Vec<[F; POSEIDON2_WIDTH]>, [F; DIGEST_SIZE]) {
16    let n = elements.len();
17    assert!(n > 1);
18
19    let flat: Vec<F> = elements.iter().flatten().copied().collect();
20    let (result, pre_states, post_states) = poseidon2_hash_slice_with_states(&flat);
21
22    debug_assert_eq!(post_states.len(), n);
23    debug_assert_eq!(pre_states.len(), n);
24
25    if let Some(permute) = poseidon2_permute_inputs {
26        permute.extend_from_slice(&pre_states[..n - 1]);
27    }
28    if let Some(compress) = poseidon2_compress_inputs {
29        compress.push(pre_states[n - 1]);
30    }
31
32    let intermediate = post_states[..n - 1].to_vec();
33    (intermediate, result)
34}