use alloc::sync::Arc;
use miden_air::trace::{RowIndex, chiplets::hasher::STATE_WIDTH, decoder::NUM_USER_OP_HELPERS};
use miden_core::{
Felt, Word, ZERO,
crypto::merkle::MerklePath,
field::{BasedVectorSpace, Field, QuadFelt},
mast::{MastForest, MastNodeId},
};
use crate::{
ContextId,
continuation_stack::{Continuation, ContinuationStack},
trace::{chiplets::CircuitEvaluation, utils::split_u32_into_u16},
};
pub trait Tracer {
type Processor;
fn start_clock_cycle(
&mut self,
processor: &Self::Processor,
continuation: Continuation,
continuation_stack: &ContinuationStack,
current_forest: &Arc<MastForest>,
);
fn finalize_clock_cycle(
&mut self,
processor: &Self::Processor,
op_helper_registers: OperationHelperRegisters,
current_forest: &Arc<MastForest>,
);
fn record_mast_forest_resolution(&mut self, _node_id: MastNodeId, _forest: &Arc<MastForest>) {}
fn record_hasher_permute(
&mut self,
_input_state: [Felt; STATE_WIDTH],
_output_state: [Felt; STATE_WIDTH],
) {
}
fn record_hasher_build_merkle_root(
&mut self,
_node: Word,
_path: Option<&MerklePath>,
_index: Felt,
_output_root: Word,
) {
}
fn record_hasher_update_merkle_root(
&mut self,
_old_value: Word,
_new_value: Word,
_path: Option<&MerklePath>,
_index: Felt,
_old_root: Word,
_new_root: Word,
) {
}
fn record_memory_read_element(
&mut self,
_element: Felt,
_addr: Felt,
_ctx: ContextId,
_clk: RowIndex,
) {
}
fn record_memory_read_word(
&mut self,
_word: Word,
_addr: Felt,
_ctx: ContextId,
_clk: RowIndex,
) {
}
fn record_memory_write_element(
&mut self,
_element: Felt,
_addr: Felt,
_ctx: ContextId,
_clk: RowIndex,
) {
}
fn record_memory_write_word(
&mut self,
_word: Word,
_addr: Felt,
_ctx: ContextId,
_clk: RowIndex,
) {
}
fn record_memory_read_element_pair(
&mut self,
_element_0: Felt,
_addr_0: Felt,
_element_1: Felt,
_addr_1: Felt,
_ctx: ContextId,
_clk: RowIndex,
) {
}
fn record_memory_read_dword(
&mut self,
_words: [Word; 2],
_addr: Felt,
_ctx: ContextId,
_clk: RowIndex,
) {
}
fn record_dyncall_memory(
&mut self,
_callee_hash: Word,
_read_addr: Felt,
_read_ctx: ContextId,
_fmp_ctx: ContextId,
_clk: RowIndex,
) {
}
fn record_crypto_stream(
&mut self,
_plaintext: [Word; 2],
_src_addr: Felt,
_ciphertext: [Word; 2],
_dst_addr: Felt,
_ctx: ContextId,
_clk: RowIndex,
) {
}
fn record_pipe(&mut self, _words: [Word; 2], _addr: Felt, _ctx: ContextId, _clk: RowIndex) {}
fn record_advice_pop_stack(&mut self, _value: Felt) {}
fn record_advice_pop_stack_word(&mut self, _word: Word) {}
fn record_u32and(&mut self, _a: Felt, _b: Felt) {}
fn record_u32xor(&mut self, _a: Felt, _b: Felt) {}
fn record_u32_range_checks(&mut self, _clk: RowIndex, _u32_lo: Felt, _u32_hi: Felt) {}
fn record_kernel_proc_access(&mut self, _proc_hash: Word) {}
fn record_circuit_evaluation(&mut self, _circuit_evaluation: CircuitEvaluation) {}
}
#[derive(Debug, Clone)]
pub enum OperationHelperRegisters {
Eq { stack_second: Felt, stack_first: Felt },
U32Split { lo: Felt, hi: Felt },
Eqz { top: Felt },
Expacc { acc_update_val: Felt },
FriExt2Fold4 {
ev: QuadFelt,
es: QuadFelt,
x: Felt,
x_inv: Felt,
},
U32Add { sum: Felt, carry: Felt },
U32Add3 { sum: Felt, carry: Felt },
U32Sub { second_new: Felt },
U32Mul { lo: Felt, hi: Felt },
U32Madd { lo: Felt, hi: Felt },
U32Div { lo: Felt, hi: Felt },
U32Assert2 { first: Felt, second: Felt },
HPerm { addr: Felt },
MerklePath { addr: Felt },
HornerEvalBase {
alpha: QuadFelt,
tmp0: QuadFelt,
tmp1: QuadFelt,
},
HornerEvalExt {
alpha: QuadFelt,
k0: Felt,
k1: Felt,
acc_tmp: QuadFelt,
},
LogPrecompile { addr: Felt, cap_prev: Word },
Empty,
}
impl OperationHelperRegisters {
pub fn to_user_op_helpers(&self) -> [Felt; NUM_USER_OP_HELPERS] {
match self {
Self::Eq { stack_second, stack_first } => {
let h0 = if stack_second == stack_first {
ZERO
} else {
(*stack_first - *stack_second).inverse()
};
[h0, ZERO, ZERO, ZERO, ZERO, ZERO]
},
Self::U32Split { lo, hi } => {
let (t1, t0) = split_u32_into_u16(lo.as_canonical_u64());
let (t3, t2) = split_u32_into_u16(hi.as_canonical_u64());
let m = (Felt::from_u32(u32::MAX) - *hi).try_inverse().unwrap_or(ZERO);
[
Felt::from_u16(t0),
Felt::from_u16(t1),
Felt::from_u16(t2),
Felt::from_u16(t3),
m,
ZERO,
]
},
Self::Eqz { top } => {
let h0 = top.try_inverse().unwrap_or(ZERO);
[h0, ZERO, ZERO, ZERO, ZERO, ZERO]
},
Self::Expacc { acc_update_val } => [*acc_update_val, ZERO, ZERO, ZERO, ZERO, ZERO],
Self::FriExt2Fold4 { ev, es, x, x_inv } => {
let ev_felts = ev.as_basis_coefficients_slice();
let es_felts = es.as_basis_coefficients_slice();
[ev_felts[0], ev_felts[1], es_felts[0], es_felts[1], *x, *x_inv]
},
Self::U32Add { sum, carry } => {
let (t1, t0) = split_u32_into_u16(sum.as_canonical_u64());
let (t3, t2) = split_u32_into_u16(carry.as_canonical_u64());
[
Felt::from_u16(t0),
Felt::from_u16(t1),
Felt::from_u16(t2),
Felt::from_u16(t3),
ZERO,
ZERO,
]
},
Self::U32Add3 { sum, carry } => {
let (t1, t0) = split_u32_into_u16(sum.as_canonical_u64());
let (t3, t2) = split_u32_into_u16(carry.as_canonical_u64());
[
Felt::from_u16(t0),
Felt::from_u16(t1),
Felt::from_u16(t2),
Felt::from_u16(t3),
ZERO,
ZERO,
]
},
Self::U32Sub { second_new } => {
let (t1, t0) = split_u32_into_u16(second_new.as_canonical_u64());
[Felt::from_u16(t0), Felt::from_u16(t1), ZERO, ZERO, ZERO, ZERO]
},
Self::U32Mul { lo, hi } => {
let (t1, t0) = split_u32_into_u16(lo.as_canonical_u64());
let (t3, t2) = split_u32_into_u16(hi.as_canonical_u64());
let m = (Felt::from_u32(u32::MAX) - *hi).try_inverse().unwrap_or(ZERO);
[
Felt::from_u16(t0),
Felt::from_u16(t1),
Felt::from_u16(t2),
Felt::from_u16(t3),
m,
ZERO,
]
},
Self::U32Madd { lo, hi } => {
let (t1, t0) = split_u32_into_u16(lo.as_canonical_u64());
let (t3, t2) = split_u32_into_u16(hi.as_canonical_u64());
let m = (Felt::from_u32(u32::MAX) - *hi).try_inverse().unwrap_or(ZERO);
[
Felt::from_u16(t0),
Felt::from_u16(t1),
Felt::from_u16(t2),
Felt::from_u16(t3),
m,
ZERO,
]
},
Self::U32Div { lo, hi } => {
let (t1, t0) = split_u32_into_u16(lo.as_canonical_u64());
let (t3, t2) = split_u32_into_u16(hi.as_canonical_u64());
[
Felt::from_u16(t0),
Felt::from_u16(t1),
Felt::from_u16(t2),
Felt::from_u16(t3),
ZERO,
ZERO,
]
},
Self::U32Assert2 { first, second } => {
let (t1, t0) = split_u32_into_u16(second.as_canonical_u64());
let (t3, t2) = split_u32_into_u16(first.as_canonical_u64());
[
Felt::from_u16(t0),
Felt::from_u16(t1),
Felt::from_u16(t2),
Felt::from_u16(t3),
ZERO,
ZERO,
]
},
Self::HPerm { addr } => [*addr, ZERO, ZERO, ZERO, ZERO, ZERO],
Self::MerklePath { addr } => [*addr, ZERO, ZERO, ZERO, ZERO, ZERO],
Self::HornerEvalBase { alpha, tmp0, tmp1 } => [
alpha.as_basis_coefficients_slice()[0],
alpha.as_basis_coefficients_slice()[1],
tmp1.as_basis_coefficients_slice()[0],
tmp1.as_basis_coefficients_slice()[1],
tmp0.as_basis_coefficients_slice()[0],
tmp0.as_basis_coefficients_slice()[1],
],
Self::HornerEvalExt { alpha, k0, k1, acc_tmp } => [
alpha.as_basis_coefficients_slice()[0],
alpha.as_basis_coefficients_slice()[1],
*k0,
*k1,
acc_tmp.as_basis_coefficients_slice()[0],
acc_tmp.as_basis_coefficients_slice()[1],
],
Self::LogPrecompile { addr, cap_prev } => {
[*addr, cap_prev[0], cap_prev[1], cap_prev[2], cap_prev[3], ZERO]
},
Self::Empty => [ZERO; NUM_USER_OP_HELPERS],
}
}
}