use miden_core::field::PrimeCharacteristicRing;
use miden_crypto::stark::air::AirBuilder;
use super::selectors::ChipletFlags;
use crate::{
MainCols, MidenAirBuilder,
constraints::{
constants::{F_1, F_4},
ext_field::{QuadFeltAirBuilder, QuadFeltExpr},
utils::BoolNot,
},
};
pub fn enforce_ace_constraints_all_rows<AB>(
builder: &mut AB,
local: &MainCols<AB::Var>,
next: &MainCols<AB::Var>,
flags: &ChipletFlags<AB::Expr>,
) where
AB: MidenAirBuilder,
{
let local = local.ace();
let next = next.ace();
let ace_flag = flags.is_active.clone();
let ace_transition = flags.is_transition.clone();
let ace_last = flags.is_last.clone();
let s_start = local.s_start;
let s_start_next = next.s_start;
let s_transition = s_start_next.into().not();
builder.when(flags.next_is_first.clone()).assert_one(s_start_next);
{
let builder = &mut builder.when(ace_flag.clone());
builder.assert_bool(local.s_start);
builder.assert_bool(local.s_block);
}
let f_eval = local.s_block;
let f_eval_next = next.s_block;
let f_read = f_eval.into().not();
let f_read_next = f_eval_next.into().not();
{
builder.when(ace_last).assert_zero(s_start);
builder.when(ace_transition.clone()).when(s_start).assert_zero(s_start_next);
builder.when(ace_flag.clone()).when(s_start).assert_zero(f_eval);
builder
.when(ace_transition.clone())
.when(s_transition.clone())
.when(f_eval)
.assert_zero(f_read_next.clone());
}
{
let builder = &mut builder.when(ace_transition.clone() * s_transition);
builder.assert_eq(next.ctx, local.ctx);
builder.assert_eq(next.clk, local.clk);
let expected_ptr: AB::Expr = local.ptr + f_read.clone() * F_4 + f_eval;
builder.assert_eq(next.ptr, expected_ptr);
let expected_id0: AB::Expr = next.id_0 + f_read.double() + f_eval;
builder.assert_eq(local.id_0, expected_id0);
}
builder
.when(ace_flag.clone())
.when(f_read.clone())
.assert_eq(local.id_1, local.id_0 - F_1);
let selected: AB::Expr = f_read_next * next.read().num_eval + f_eval_next * next.id_0;
builder
.when(ace_transition)
.when(f_read.clone())
.assert_eq(selected, local.read().num_eval);
{
let builder = &mut builder.when(ace_flag * f_eval);
let op: AB::Expr = local.eval_op.into();
let op_square = op.square();
builder.assert_zero(op.clone() * (op_square.clone() - F_1));
let v0: QuadFeltExpr<AB::Expr> = local.v_0.into_expr();
let v1: QuadFeltExpr<AB::Expr> = local.v_1.into_expr();
let v2: QuadFeltExpr<AB::Expr> = local.eval().v_2.into_expr();
let expected = {
let linear = v1.clone() + v2.clone() * op;
let nonlinear = v1 * v2;
(linear - nonlinear.clone()) * op_square + nonlinear
};
builder.assert_eq_quad(v0, expected);
}
{
let f_end = flags.is_last.clone() + flags.is_transition.clone() * s_start_next;
let builder = &mut builder.when(f_end);
builder.assert_zero(f_read);
let v0: QuadFeltExpr<AB::Expr> = local.v_0.into_expr();
builder.assert_eq_quad(v0, QuadFeltExpr::new(AB::Expr::ZERO, AB::Expr::ZERO));
builder.assert_zero(local.id_0);
}
}