use super::{
super::{Trace, NUM_RAND_ROWS},
build_trace_from_ops_with_inputs, rand_array, Felt, LookupTableRow, Operation, ProgramInputs,
Word, ONE, ZERO,
};
use crate::chiplets::SiblingTableRow;
use vm_core::{
chiplets::hasher::P1_COL_IDX, AdviceSet, FieldElement, StarkField, AUX_TRACE_RAND_ELEMENTS,
};
#[test]
#[allow(clippy::needless_range_loop)]
fn hasher_p1_mp_verify() {
let tree = build_merkle_tree();
let node = tree.get_node(3, 1).unwrap();
let mut init_stack = vec![];
append_word(&mut init_stack, node);
init_stack.extend_from_slice(&[3, 1]);
append_word(&mut init_stack, tree.root());
init_stack.reverse();
let inputs = ProgramInputs::new(&init_stack, &[], vec![tree]).unwrap();
let ops = vec![Operation::MpVerify];
let mut trace = build_trace_from_ops_with_inputs(ops, inputs);
let alphas = rand_array::<Felt, AUX_TRACE_RAND_ELEMENTS>();
let aux_columns = trace.build_aux_segment(&[], &alphas).unwrap();
let p1 = aux_columns.get_column(P1_COL_IDX);
for i in 0..(p1.len() - NUM_RAND_ROWS) {
assert_eq!(ONE, p1[i]);
}
}
#[test]
#[allow(clippy::needless_range_loop)]
fn hasher_p1_mr_update() {
let tree = build_merkle_tree();
let index = 5_u64;
let old_node = tree.get_node(3, index).unwrap();
let new_node = init_leaf(11);
let path = tree.get_path(3, index).unwrap();
let mut init_stack = vec![];
append_word(&mut init_stack, old_node);
init_stack.extend_from_slice(&[3, index]);
append_word(&mut init_stack, tree.root());
append_word(&mut init_stack, new_node);
init_stack.reverse();
let inputs = ProgramInputs::new(&init_stack, &[], vec![tree]).unwrap();
let ops = vec![Operation::MrUpdate(false)];
let mut trace = build_trace_from_ops_with_inputs(ops, inputs);
let alphas = rand_array::<Felt, AUX_TRACE_RAND_ELEMENTS>();
let aux_columns = trace.build_aux_segment(&[], &alphas).unwrap();
let p1 = aux_columns.get_column(P1_COL_IDX);
let row_values = [
SiblingTableRow::new(Felt::new(index), path[0]).to_value(&trace.main_trace, &alphas),
SiblingTableRow::new(Felt::new(index >> 1), path[1]).to_value(&trace.main_trace, &alphas),
SiblingTableRow::new(Felt::new(index >> 2), path[2]).to_value(&trace.main_trace, &alphas),
];
let mut expected_value = ONE;
assert_eq!(expected_value, p1[0]);
for i in 1..8 {
assert_eq!(expected_value, p1[i]);
}
expected_value *= row_values[0];
assert_eq!(expected_value, p1[9]);
for i in 10..17 {
assert_eq!(expected_value, p1[i]);
}
expected_value *= row_values[1];
assert_eq!(expected_value, p1[17]);
for i in 18..25 {
assert_eq!(expected_value, p1[i]);
}
expected_value *= row_values[2];
assert_eq!(expected_value, p1[25]);
for i in 25..33 {
assert_eq!(expected_value, p1[i]);
}
expected_value *= row_values[0].inv();
assert_eq!(expected_value, p1[33]);
for i in 33..41 {
assert_eq!(expected_value, p1[i]);
}
expected_value *= row_values[1].inv();
assert_eq!(expected_value, p1[41]);
for i in 41..49 {
assert_eq!(expected_value, p1[i]);
}
expected_value *= row_values[2].inv();
assert_eq!(expected_value, p1[49]);
assert_eq!(expected_value, ONE);
for i in 50..(p1.len() - NUM_RAND_ROWS) {
assert_eq!(ONE, p1[i]);
}
}
fn build_merkle_tree() -> AdviceSet {
let leaves = init_leaves(&[1, 2, 3, 4, 5, 6, 7, 8]);
AdviceSet::new_merkle_tree(leaves.to_vec()).unwrap()
}
fn init_leaves(values: &[u64]) -> Vec<Word> {
values.iter().map(|&v| init_leaf(v)).collect()
}
fn init_leaf(value: u64) -> Word {
[Felt::new(value), ZERO, ZERO, ZERO]
}
fn append_word(target: &mut Vec<u64>, word: Word) {
word.iter().rev().for_each(|v| target.push(v.as_int()));
}