use alloc::vec::Vec;
use miden_core::{WORD_SIZE, field::PrimeCharacteristicRing};
use super::{Felt, KERNEL_ROM_TRACE_WIDTH, Kernel, KernelRom, TraceFragment};
use crate::{ONE, ZERO};
const PROC1_HASH: [Felt; WORD_SIZE] = [ONE, ZERO, ONE, ZERO];
const PROC2_HASH: [Felt; WORD_SIZE] = [ONE, ONE, ONE, ONE];
#[test]
fn kernel_rom_invalid_access() {
let kernel = build_kernel();
let mut rom = KernelRom::new(kernel);
assert!(rom.access_proc(PROC1_HASH.into()).is_ok());
assert!(rom.access_proc([ZERO, ONE, ZERO, ONE].into()).is_err());
}
#[test]
fn kernel_rom_no_access() {
let kernel = build_kernel();
let rom = KernelRom::new(kernel);
let expected_trace_len = 2;
assert_eq!(expected_trace_len, rom.trace_len());
let trace = build_trace(rom, expected_trace_len);
assert_row(&trace, 0, ZERO, PROC1_HASH);
assert_row(&trace, 1, ZERO, PROC2_HASH);
}
#[test]
fn kernel_rom_with_access() {
let kernel = build_kernel();
let mut rom = KernelRom::new(kernel);
rom.access_proc(PROC1_HASH.into()).unwrap();
rom.access_proc(PROC2_HASH.into()).unwrap();
rom.access_proc(PROC1_HASH.into()).unwrap();
rom.access_proc(PROC1_HASH.into()).unwrap();
rom.access_proc(PROC2_HASH.into()).unwrap();
let expected_trace_len = 2;
assert_eq!(expected_trace_len, rom.trace_len());
let trace = build_trace(rom, expected_trace_len);
assert_row(&trace, 0, Felt::from_u64(3), PROC1_HASH);
assert_row(&trace, 1, Felt::from_u64(2), PROC2_HASH);
}
#[test]
fn kernel_rom_with_single_access() {
let kernel = build_kernel();
let mut rom = KernelRom::new(kernel);
rom.access_proc(PROC1_HASH.into()).unwrap();
rom.access_proc(PROC1_HASH.into()).unwrap();
let expected_trace_len = 2;
assert_eq!(expected_trace_len, rom.trace_len());
let trace = build_trace(rom, expected_trace_len);
assert_row(&trace, 0, Felt::from_u64(2), PROC1_HASH);
assert_row(&trace, 1, ZERO, PROC2_HASH);
}
fn build_kernel() -> Kernel {
Kernel::new(&[PROC1_HASH.into(), PROC2_HASH.into()]).unwrap()
}
fn build_trace(kernel_rom: KernelRom, num_rows: usize) -> Vec<Vec<Felt>> {
let mut trace = (0..KERNEL_ROM_TRACE_WIDTH).map(|_| vec![ZERO; num_rows]).collect::<Vec<_>>();
let mut fragment = TraceFragment::trace_to_fragment(&mut trace);
kernel_rom.fill_trace(&mut fragment);
trace
}
fn assert_row(trace: &[Vec<Felt>], row: usize, multiplicity: Felt, digest: [Felt; WORD_SIZE]) {
assert_eq!(trace[0][row], multiplicity, "multiplicity mismatch at row {row}");
assert_eq!(trace[1][row], digest[0], "digest[0] mismatch at row {row}");
assert_eq!(trace[2][row], digest[1], "digest[1] mismatch at row {row}");
assert_eq!(trace[3][row], digest[2], "digest[2] mismatch at row {row}");
assert_eq!(trace[4][row], digest[3], "digest[3] mismatch at row {row}");
}