use alloc::vec::Vec;
use miden_core::{
Felt, Word, ZERO,
chiplets::hasher::{STATE_WIDTH, apply_permutation},
crypto::merkle::{MerkleStore, MerkleTree, NodeIndex},
field::{BasedVectorSpace, QuadFelt},
mast::MastForest,
program::StackInputs,
};
use proptest::prelude::*;
use super::{
op_crypto_stream, op_horner_eval_base, op_horner_eval_ext, op_hperm, op_mpverify, op_mrupdate,
};
use crate::{
AdviceInputs, ContextId,
fast::{FastProcessor, NoopTracer},
processor::{Processor, SystemInterface},
};
const ALPHA_ADDR: u64 = 1000;
proptest! {
#[test]
fn test_op_hperm(
s0 in any::<u64>(),
s1 in any::<u64>(),
s2 in any::<u64>(),
s3 in any::<u64>(),
s4 in any::<u64>(),
s5 in any::<u64>(),
s6 in any::<u64>(),
s7 in any::<u64>(),
s8 in any::<u64>(),
s9 in any::<u64>(),
s10 in any::<u64>(),
s11 in any::<u64>(),
s12 in any::<u64>(),
s13 in any::<u64>(),
s14 in any::<u64>(),
s15 in any::<u64>(),
) {
let stack_inputs = [
Felt::new_unchecked(s0), Felt::new_unchecked(s1), Felt::new_unchecked(s2), Felt::new_unchecked(s3), Felt::new_unchecked(s4), Felt::new_unchecked(s5), Felt::new_unchecked(s6), Felt::new_unchecked(s7), Felt::new_unchecked(s8), Felt::new_unchecked(s9), Felt::new_unchecked(s10), Felt::new_unchecked(s11), Felt::new_unchecked(s12), Felt::new_unchecked(s13), Felt::new_unchecked(s14), Felt::new_unchecked(s15), ];
let mut processor = FastProcessor::new(StackInputs::new(&stack_inputs).unwrap());
let mut tracer = NoopTracer;
let expected_state = {
let mut expected_state = [
Felt::new_unchecked(s0),
Felt::new_unchecked(s1),
Felt::new_unchecked(s2),
Felt::new_unchecked(s3),
Felt::new_unchecked(s4),
Felt::new_unchecked(s5),
Felt::new_unchecked(s6),
Felt::new_unchecked(s7),
Felt::new_unchecked(s8),
Felt::new_unchecked(s9),
Felt::new_unchecked(s10),
Felt::new_unchecked(s11),
];
apply_permutation(&mut expected_state);
expected_state
};
let _ = op_hperm(&mut processor, &mut tracer);
processor.system_mut().increment_clock();
let stack = processor.stack_top();
for i in 0..STATE_WIDTH {
prop_assert_eq!(
stack[15 - i],
expected_state[i],
"mismatch at position {} (expected_state[{}])",
i,
i
);
}
prop_assert_eq!(stack[3], Felt::new_unchecked(s12), "s12 at position 12");
prop_assert_eq!(stack[2], Felt::new_unchecked(s13), "s13 at position 13");
prop_assert_eq!(stack[1], Felt::new_unchecked(s14), "s14 at position 14");
prop_assert_eq!(stack[0], Felt::new_unchecked(s15), "s15 at position 15");
}
}
proptest! {
#[test]
fn test_op_crypto_stream(
r0 in any::<u64>(),
r1 in any::<u64>(),
r2 in any::<u64>(),
r3 in any::<u64>(),
r4 in any::<u64>(),
r5 in any::<u64>(),
r6 in any::<u64>(),
r7 in any::<u64>(),
c0 in any::<u64>(),
c1 in any::<u64>(),
c2 in any::<u64>(),
c3 in any::<u64>(),
p0 in any::<u64>(),
p1 in any::<u64>(),
p2 in any::<u64>(),
p3 in any::<u64>(),
p4 in any::<u64>(),
p5 in any::<u64>(),
p6 in any::<u64>(),
p7 in any::<u64>(),
) {
let src_addr: u64 = 1000;
let dst_addr: u64 = 2000;
let stack_inputs = [
Felt::new_unchecked(r0), Felt::new_unchecked(r1), Felt::new_unchecked(r2), Felt::new_unchecked(r3), Felt::new_unchecked(r4), Felt::new_unchecked(r5), Felt::new_unchecked(r6), Felt::new_unchecked(r7), Felt::new_unchecked(c0), Felt::new_unchecked(c1), Felt::new_unchecked(c2), Felt::new_unchecked(c3), Felt::new_unchecked(src_addr), Felt::new_unchecked(dst_addr), ZERO, ZERO, ];
let mut processor = FastProcessor::new(StackInputs::new(&stack_inputs).unwrap());
let mut tracer = NoopTracer;
let plaintext_word1: Word = [Felt::new_unchecked(p0), Felt::new_unchecked(p1), Felt::new_unchecked(p2), Felt::new_unchecked(p3)].into();
let plaintext_word2: Word = [Felt::new_unchecked(p4), Felt::new_unchecked(p5), Felt::new_unchecked(p6), Felt::new_unchecked(p7)].into();
let clk = processor.clock();
processor.memory_mut().write_word(
ContextId::root(),
Felt::new_unchecked(src_addr),
clk,
plaintext_word1,
).unwrap();
processor.system_mut().increment_clock();
let clk = processor.clock();
processor.memory_mut().write_word(
ContextId::root(),
Felt::new_unchecked(src_addr + 4),
clk,
plaintext_word2,
).unwrap();
processor.system_mut().increment_clock();
let result = op_crypto_stream(&mut processor, &mut tracer);
prop_assert!(result.is_ok());
processor.system_mut().increment_clock();
let expected_cipher1 = [
Felt::new_unchecked(p0) + Felt::new_unchecked(r0),
Felt::new_unchecked(p1) + Felt::new_unchecked(r1),
Felt::new_unchecked(p2) + Felt::new_unchecked(r2),
Felt::new_unchecked(p3) + Felt::new_unchecked(r3),
];
let expected_cipher2 = [
Felt::new_unchecked(p4) + Felt::new_unchecked(r4),
Felt::new_unchecked(p5) + Felt::new_unchecked(r5),
Felt::new_unchecked(p6) + Felt::new_unchecked(r6),
Felt::new_unchecked(p7) + Felt::new_unchecked(r7),
];
let clk = processor.clock();
let cipher_word1 = processor.memory_mut().read_word(ContextId::root(), Felt::new_unchecked(dst_addr), clk).unwrap();
let cipher_word2 = processor.memory_mut().read_word(ContextId::root(), Felt::new_unchecked(dst_addr + 4), clk).unwrap();
prop_assert_eq!(cipher_word1[0], expected_cipher1[0], "cipher word1[0]");
prop_assert_eq!(cipher_word1[1], expected_cipher1[1], "cipher word1[1]");
prop_assert_eq!(cipher_word1[2], expected_cipher1[2], "cipher word1[2]");
prop_assert_eq!(cipher_word1[3], expected_cipher1[3], "cipher word1[3]");
prop_assert_eq!(cipher_word2[0], expected_cipher2[0], "cipher word2[0]");
prop_assert_eq!(cipher_word2[1], expected_cipher2[1], "cipher word2[1]");
prop_assert_eq!(cipher_word2[2], expected_cipher2[2], "cipher word2[2]");
prop_assert_eq!(cipher_word2[3], expected_cipher2[3], "cipher word2[3]");
let stack = processor.stack_top();
prop_assert_eq!(stack[15], expected_cipher1[0], "cipher1[0] at position 0");
prop_assert_eq!(stack[14], expected_cipher1[1], "cipher1[1] at position 1");
prop_assert_eq!(stack[13], expected_cipher1[2], "cipher1[2] at position 2");
prop_assert_eq!(stack[12], expected_cipher1[3], "cipher1[3] at position 3");
prop_assert_eq!(stack[11], expected_cipher2[0], "cipher2[0] at position 4");
prop_assert_eq!(stack[10], expected_cipher2[1], "cipher2[1] at position 5");
prop_assert_eq!(stack[9], expected_cipher2[2], "cipher2[2] at position 6");
prop_assert_eq!(stack[8], expected_cipher2[3], "cipher2[3] at position 7");
prop_assert_eq!(stack[7], Felt::new_unchecked(c0), "c0 at position 8");
prop_assert_eq!(stack[6], Felt::new_unchecked(c1), "c1 at position 9");
prop_assert_eq!(stack[5], Felt::new_unchecked(c2), "c2 at position 10");
prop_assert_eq!(stack[4], Felt::new_unchecked(c3), "c3 at position 11");
prop_assert_eq!(stack[3], Felt::new_unchecked(src_addr + 8), "src_ptr incremented");
prop_assert_eq!(stack[2], Felt::new_unchecked(dst_addr + 8), "dst_ptr incremented");
}
}
proptest! {
#[test]
fn test_op_horner_eval_base(
c0 in any::<u64>(),
c1 in any::<u64>(),
c2 in any::<u64>(),
c3 in any::<u64>(),
c4 in any::<u64>(),
c5 in any::<u64>(),
c6 in any::<u64>(),
c7 in any::<u64>(),
s8 in any::<u64>(),
s9 in any::<u64>(),
s10 in any::<u64>(),
s11 in any::<u64>(),
s12 in any::<u64>(),
alpha_0 in any::<u64>(),
alpha_1 in any::<u64>(),
acc_0 in any::<u64>(),
acc_1 in any::<u64>(),
) {
let stack_inputs = [
Felt::new_unchecked(c0), Felt::new_unchecked(c1), Felt::new_unchecked(c2), Felt::new_unchecked(c3), Felt::new_unchecked(c4), Felt::new_unchecked(c5), Felt::new_unchecked(c6), Felt::new_unchecked(c7), Felt::new_unchecked(s8), Felt::new_unchecked(s9), Felt::new_unchecked(s10), Felt::new_unchecked(s11), Felt::new_unchecked(s12), Felt::new_unchecked(ALPHA_ADDR), Felt::new_unchecked(acc_0), Felt::new_unchecked(acc_1), ];
let mut processor = FastProcessor::new(StackInputs::new(&stack_inputs).unwrap());
let mut tracer = NoopTracer;
let alpha_word: Word = [Felt::new_unchecked(alpha_0), Felt::new_unchecked(alpha_1), ZERO, ZERO].into();
let clk = processor.clock();
processor.memory_mut().write_word(
ContextId::root(),
Felt::new_unchecked(ALPHA_ADDR),
clk,
alpha_word,
).unwrap();
processor.system_mut().increment_clock();
let result = op_horner_eval_base(&mut processor, &mut tracer);
prop_assert!(result.is_ok());
processor.system_mut().increment_clock();
let alpha = QuadFelt::new([Felt::new_unchecked(alpha_0), Felt::new_unchecked(alpha_1)]);
let acc_old = QuadFelt::new([Felt::new_unchecked(acc_0), Felt::new_unchecked(acc_1)]);
let c0_q = QuadFelt::from(Felt::new_unchecked(c0));
let c1_q = QuadFelt::from(Felt::new_unchecked(c1));
let c2_q = QuadFelt::from(Felt::new_unchecked(c2));
let c3_q = QuadFelt::from(Felt::new_unchecked(c3));
let c4_q = QuadFelt::from(Felt::new_unchecked(c4));
let c5_q = QuadFelt::from(Felt::new_unchecked(c5));
let c6_q = QuadFelt::from(Felt::new_unchecked(c6));
let c7_q = QuadFelt::from(Felt::new_unchecked(c7));
let tmp0 = (acc_old * alpha + c0_q) * alpha + c1_q;
let tmp1 = ((tmp0 * alpha + c2_q) * alpha + c3_q) * alpha + c4_q;
let acc_new = ((tmp1 * alpha + c5_q) * alpha + c6_q) * alpha + c7_q;
let stack = processor.stack_top();
prop_assert_eq!(stack[15], Felt::new_unchecked(c0), "c0 at position 0 (top)");
prop_assert_eq!(stack[14], Felt::new_unchecked(c1), "c1 at position 1");
prop_assert_eq!(stack[13], Felt::new_unchecked(c2), "c2 at position 2");
prop_assert_eq!(stack[12], Felt::new_unchecked(c3), "c3 at position 3");
prop_assert_eq!(stack[11], Felt::new_unchecked(c4), "c4 at position 4");
prop_assert_eq!(stack[10], Felt::new_unchecked(c5), "c5 at position 5");
prop_assert_eq!(stack[9], Felt::new_unchecked(c6), "c6 at position 6");
prop_assert_eq!(stack[8], Felt::new_unchecked(c7), "c7 at position 7");
prop_assert_eq!(stack[7], Felt::new_unchecked(s8), "s8 at position 8");
prop_assert_eq!(stack[6], Felt::new_unchecked(s9), "s9 at position 9");
prop_assert_eq!(stack[5], Felt::new_unchecked(s10), "s10 at position 10");
prop_assert_eq!(stack[4], Felt::new_unchecked(s11), "s11 at position 11");
prop_assert_eq!(stack[3], Felt::new_unchecked(s12), "s12 at position 12");
prop_assert_eq!(stack[2], Felt::new_unchecked(ALPHA_ADDR), "alpha_addr at position 13");
let acc_new_base: &[Felt] = acc_new.as_basis_coefficients_slice();
prop_assert_eq!(stack[1], acc_new_base[0], "acc_low at position 14");
prop_assert_eq!(stack[0], acc_new_base[1], "acc_high at position 15");
}
#[test]
fn test_op_horner_eval_ext(
c0_0 in any::<u64>(),
c0_1 in any::<u64>(),
c1_0 in any::<u64>(),
c1_1 in any::<u64>(),
c2_0 in any::<u64>(),
c2_1 in any::<u64>(),
c3_0 in any::<u64>(),
c3_1 in any::<u64>(),
s8 in any::<u64>(),
s9 in any::<u64>(),
s10 in any::<u64>(),
s11 in any::<u64>(),
s12 in any::<u64>(),
alpha_0 in any::<u64>(),
alpha_1 in any::<u64>(),
acc_0 in any::<u64>(),
acc_1 in any::<u64>(),
) {
let stack_inputs = [
Felt::new_unchecked(c0_0), Felt::new_unchecked(c0_1), Felt::new_unchecked(c1_0), Felt::new_unchecked(c1_1), Felt::new_unchecked(c2_0), Felt::new_unchecked(c2_1), Felt::new_unchecked(c3_0), Felt::new_unchecked(c3_1), Felt::new_unchecked(s8), Felt::new_unchecked(s9), Felt::new_unchecked(s10), Felt::new_unchecked(s11), Felt::new_unchecked(s12), Felt::new_unchecked(ALPHA_ADDR), Felt::new_unchecked(acc_0), Felt::new_unchecked(acc_1), ];
let mut processor = FastProcessor::new(StackInputs::new(&stack_inputs).unwrap());
let mut tracer = NoopTracer;
let alpha_word: Word = [Felt::new_unchecked(alpha_0), Felt::new_unchecked(alpha_1), ZERO, ZERO].into();
let clk = processor.clock();
processor.memory_mut().write_word(
ContextId::root(),
Felt::new_unchecked(ALPHA_ADDR),
clk,
alpha_word,
).unwrap();
processor.system_mut().increment_clock();
let result = op_horner_eval_ext(&mut processor, &mut tracer);
prop_assert!(result.is_ok());
processor.system_mut().increment_clock();
let alpha = QuadFelt::new([Felt::new_unchecked(alpha_0), Felt::new_unchecked(alpha_1)]);
let acc_old = QuadFelt::new([Felt::new_unchecked(acc_0), Felt::new_unchecked(acc_1)]);
let c0 = QuadFelt::new([Felt::new_unchecked(c0_0), Felt::new_unchecked(c0_1)]);
let c1 = QuadFelt::new([Felt::new_unchecked(c1_0), Felt::new_unchecked(c1_1)]);
let c2 = QuadFelt::new([Felt::new_unchecked(c2_0), Felt::new_unchecked(c2_1)]);
let c3 = QuadFelt::new([Felt::new_unchecked(c3_0), Felt::new_unchecked(c3_1)]);
let coefficients = [c0, c1, c2, c3];
let acc_tmp = coefficients.iter().take(2).fold(acc_old, |acc, coef| *coef + alpha * acc);
let acc_new = coefficients.iter().skip(2).fold(acc_tmp, |acc, coef| *coef + alpha * acc);
let stack = processor.stack_top();
prop_assert_eq!(stack[15], Felt::new_unchecked(c0_0), "c0_0 at position 0 (top, low)");
prop_assert_eq!(stack[14], Felt::new_unchecked(c0_1), "c0_1 at position 1 (high)");
prop_assert_eq!(stack[13], Felt::new_unchecked(c1_0), "c1_0 at position 2 (low)");
prop_assert_eq!(stack[12], Felt::new_unchecked(c1_1), "c1_1 at position 3 (high)");
prop_assert_eq!(stack[11], Felt::new_unchecked(c2_0), "c2_0 at position 4 (low)");
prop_assert_eq!(stack[10], Felt::new_unchecked(c2_1), "c2_1 at position 5 (high)");
prop_assert_eq!(stack[9], Felt::new_unchecked(c3_0), "c3_0 at position 6 (low)");
prop_assert_eq!(stack[8], Felt::new_unchecked(c3_1), "c3_1 at position 7 (high)");
prop_assert_eq!(stack[7], Felt::new_unchecked(s8), "s8 at position 8");
prop_assert_eq!(stack[6], Felt::new_unchecked(s9), "s9 at position 9");
prop_assert_eq!(stack[5], Felt::new_unchecked(s10), "s10 at position 10");
prop_assert_eq!(stack[4], Felt::new_unchecked(s11), "s11 at position 11");
prop_assert_eq!(stack[3], Felt::new_unchecked(s12), "s12 at position 12");
prop_assert_eq!(stack[2], Felt::new_unchecked(ALPHA_ADDR), "alpha_addr at position 13");
let acc_new_base: &[Felt] = acc_new.as_basis_coefficients_slice();
prop_assert_eq!(stack[1], acc_new_base[0], "acc_low at position 14");
prop_assert_eq!(stack[0], acc_new_base[1], "acc_high at position 15");
}
}
proptest! {
#[test]
fn test_op_mpverify(
l0 in any::<u64>(),
l1 in any::<u64>(),
l2 in any::<u64>(),
l3 in any::<u64>(),
l4 in any::<u64>(),
l5 in any::<u64>(),
l6 in any::<u64>(),
l7 in any::<u64>(),
leaf_idx in 0u64..8,
) {
let leaves: Vec<Word> = [l0, l1, l2, l3, l4, l5, l6, l7]
.iter()
.map(|&v| init_node(v))
.collect();
let tree = MerkleTree::new(&leaves).unwrap();
let store = MerkleStore::from(&tree);
let root = tree.root();
let node = leaves[leaf_idx as usize];
let depth = tree.depth() as u64;
let advice_inputs = AdviceInputs::default().with_merkle_store(store);
let stack_inputs = [
node[0], node[1], node[2], node[3], Felt::new_unchecked(depth), Felt::new_unchecked(leaf_idx), root[0], root[1], root[2], root[3], ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ];
let mut processor = FastProcessor::new(StackInputs::new(&stack_inputs).unwrap())
.with_advice(advice_inputs).expect("advice inputs should fit advice map limits");
let mut tracer = NoopTracer;
let program = MastForest::default();
let result = op_mpverify(&mut processor, ZERO, &program, &mut tracer);
prop_assert!(result.is_ok(), "op_mpverify failed: {:?}", result.err());
processor.system_mut().increment_clock();
let stack = processor.stack_top();
prop_assert_eq!(stack[15], node[0], "node[0] at position 0");
prop_assert_eq!(stack[14], node[1], "node[1] at position 1");
prop_assert_eq!(stack[13], node[2], "node[2] at position 2");
prop_assert_eq!(stack[12], node[3], "node[3] at position 3");
prop_assert_eq!(stack[11], Felt::new_unchecked(depth), "depth at position 4");
prop_assert_eq!(stack[10], Felt::new_unchecked(leaf_idx), "index at position 5");
prop_assert_eq!(stack[9], root[0], "root[0] at position 6");
prop_assert_eq!(stack[8], root[1], "root[1] at position 7");
prop_assert_eq!(stack[7], root[2], "root[2] at position 8");
prop_assert_eq!(stack[6], root[3], "root[3] at position 9");
}
#[test]
fn test_op_mrupdate(
l0 in any::<u64>(),
l1 in any::<u64>(),
l2 in any::<u64>(),
l3 in any::<u64>(),
l4 in any::<u64>(),
l5 in any::<u64>(),
l6 in any::<u64>(),
l7 in any::<u64>(),
new_leaf_value in any::<u64>(),
leaf_idx in 0u64..8,
) {
let leaves: Vec<Word> = [l0, l1, l2, l3, l4, l5, l6, l7]
.iter()
.map(|&v| init_node(v))
.collect();
let new_leaf = init_node(new_leaf_value);
let mut new_leaves = leaves.clone();
new_leaves[leaf_idx as usize] = new_leaf;
let tree = MerkleTree::new(&leaves).unwrap();
let new_tree = MerkleTree::new(&new_leaves).unwrap();
let store = MerkleStore::from(&tree);
let old_root = tree.root();
let old_node = leaves[leaf_idx as usize];
let depth = tree.depth() as u64;
let expected_new_root = new_tree.root();
let advice_inputs = AdviceInputs::default().with_merkle_store(store);
let stack_inputs = [
old_node[0], old_node[1], old_node[2], old_node[3], Felt::new_unchecked(depth), Felt::new_unchecked(leaf_idx), old_root[0], old_root[1], old_root[2], old_root[3], new_leaf[0], new_leaf[1], new_leaf[2], new_leaf[3], ZERO, ZERO, ];
let mut processor = FastProcessor::new(StackInputs::new(&stack_inputs).unwrap())
.with_advice(advice_inputs).expect("advice inputs should fit advice map limits");
let mut tracer = NoopTracer;
let result = op_mrupdate(&mut processor, &mut tracer);
prop_assert!(result.is_ok(), "op_mrupdate failed: {:?}", result.err());
processor.system_mut().increment_clock();
let stack = processor.stack_top();
prop_assert_eq!(stack[15], expected_new_root[0], "new_root[0] at position 0");
prop_assert_eq!(stack[14], expected_new_root[1], "new_root[1] at position 1");
prop_assert_eq!(stack[13], expected_new_root[2], "new_root[2] at position 2");
prop_assert_eq!(stack[12], expected_new_root[3], "new_root[3] at position 3");
prop_assert_eq!(stack[11], Felt::new_unchecked(depth), "depth at position 4");
prop_assert_eq!(stack[10], Felt::new_unchecked(leaf_idx), "index at position 5");
prop_assert_eq!(stack[9], old_root[0], "old_root[0] at position 6");
prop_assert_eq!(stack[8], old_root[1], "old_root[1] at position 7");
prop_assert_eq!(stack[7], old_root[2], "old_root[2] at position 8");
prop_assert_eq!(stack[6], old_root[3], "old_root[3] at position 9");
prop_assert_eq!(stack[5], new_leaf[0], "new_leaf[0] at position 10");
prop_assert_eq!(stack[4], new_leaf[1], "new_leaf[1] at position 11");
prop_assert_eq!(stack[3], new_leaf[2], "new_leaf[2] at position 12");
prop_assert_eq!(stack[2], new_leaf[3], "new_leaf[3] at position 13");
assert!(processor.advice_provider().has_merkle_root(tree.root()));
assert!(processor.advice_provider().has_merkle_root(new_tree.root()));
}
}
#[test]
fn test_op_mrupdate_merge_subtree() {
let leaves_a: Vec<Word> = (0..16).map(init_node).collect();
let leaves_b: Vec<Word> = (100..104).map(init_node).collect();
let mut leaves_c = leaves_a.clone();
leaves_c[4..8].copy_from_slice(&leaves_b);
let tree_a = MerkleTree::new(&leaves_a).unwrap();
let tree_b = MerkleTree::new(&leaves_b).unwrap();
let tree_c = MerkleTree::new(&leaves_c).unwrap();
let mut store = MerkleStore::default();
store.extend(tree_a.inner_nodes());
store.extend(tree_b.inner_nodes());
let target_depth = 2_u64;
let target_index = 1_u64;
let target_node = tree_b.root();
let expected_root = tree_c.root();
let replaced_root = tree_a.root();
let replaced_node = store
.get_node(replaced_root, NodeIndex::new(target_depth as u8, target_index).unwrap())
.unwrap();
let advice_inputs = AdviceInputs::default().with_merkle_store(store);
let stack_inputs = [
replaced_node[0], replaced_node[1], replaced_node[2], replaced_node[3], Felt::new_unchecked(target_depth), Felt::new_unchecked(target_index), replaced_root[0], replaced_root[1], replaced_root[2], replaced_root[3], target_node[0], target_node[1], target_node[2], target_node[3], ZERO, ZERO, ];
let mut processor = FastProcessor::new(StackInputs::new(&stack_inputs).unwrap())
.with_advice(advice_inputs)
.expect("advice inputs should fit advice map limits");
let mut tracer = NoopTracer;
let result = op_mrupdate(&mut processor, &mut tracer);
assert!(result.is_ok(), "op_mrupdate failed: {:?}", result.err());
processor.system_mut().increment_clock();
let stack = processor.stack_top();
assert_eq!(stack[15], expected_root[0], "expected_root[0] at position 0");
assert_eq!(stack[14], expected_root[1], "expected_root[1] at position 1");
assert_eq!(stack[13], expected_root[2], "expected_root[2] at position 2");
assert_eq!(stack[12], expected_root[3], "expected_root[3] at position 3");
assert_eq!(stack[11], Felt::new_unchecked(target_depth), "depth at position 4");
assert_eq!(stack[10], Felt::new_unchecked(target_index), "index at position 5");
assert_eq!(stack[9], replaced_root[0], "replaced_root[0] at position 6");
assert_eq!(stack[8], replaced_root[1], "replaced_root[1] at position 7");
assert_eq!(stack[7], replaced_root[2], "replaced_root[2] at position 8");
assert_eq!(stack[6], replaced_root[3], "replaced_root[3] at position 9");
assert_eq!(stack[5], target_node[0], "target_node[0] at position 10");
assert_eq!(stack[4], target_node[1], "target_node[1] at position 11");
assert_eq!(stack[3], target_node[2], "target_node[2] at position 12");
assert_eq!(stack[2], target_node[3], "target_node[3] at position 13");
assert!(processor.advice_provider().has_merkle_root(expected_root));
}
fn init_node(value: u64) -> Word {
[Felt::new_unchecked(value), ZERO, ZERO, ZERO].into()
}