use std::marker::PhantomData; use plonky2::field::extension::Extendable; use plonky2::field::packed::PackedField; use plonky2::hash::hash_types::RichField; use plonky2::iop::ext_target::ExtensionTarget; use plonky2::iop::target::Target; use plonky2::plonk::circuit_builder::CircuitBuilder; pub struct ConstraintConsumer { /// Random values used to combine multiple constraints into one. alphas: Vec, /// Running sums of constraints that have been emitted so far, scaled by powers of alpha. // TODO(JN): This is pub so it can be used in a test. Once we have an API for accessing this // result, it should be made private. pub constraint_accs: Vec

, /// The evaluation of `X - g^(n-1)`. z_last: P, /// The evaluation of the Lagrange basis polynomial which is nonzero at the point associated /// with the first trace row, and zero at other points in the subgroup. lagrange_basis_first: P, /// The evaluation of the Lagrange basis polynomial which is nonzero at the point associated /// with the last trace row, and zero at other points in the subgroup. lagrange_basis_last: P, } impl ConstraintConsumer

{ pub fn new( alphas: Vec, z_last: P, lagrange_basis_first: P, lagrange_basis_last: P, ) -> Self { Self { constraint_accs: vec![P::ZEROS; alphas.len()], alphas, z_last, lagrange_basis_first, lagrange_basis_last, } } pub fn accumulators(self) -> Vec

{ self.constraint_accs } /// Add one constraint valid on all rows except the last. pub fn constraint_transition(&mut self, constraint: P) { self.constraint(constraint * self.z_last); } /// Add one constraint on all rows. pub fn constraint(&mut self, constraint: P) { for (&alpha, acc) in self.alphas.iter().zip(&mut self.constraint_accs) { *acc *= alpha; *acc += constraint; } } /// Add one constraint, but first multiply it by a filter such that it will only apply to the /// first row of the trace. pub fn constraint_first_row(&mut self, constraint: P) { self.constraint(constraint * self.lagrange_basis_first); } /// Add one constraint, but first multiply it by a filter such that it will only apply to the /// last row of the trace. pub fn constraint_last_row(&mut self, constraint: P) { self.constraint(constraint * self.lagrange_basis_last); } } pub struct RecursiveConstraintConsumer, const D: usize> { /// A random value used to combine multiple constraints into one. alphas: Vec, /// A running sum of constraints that have been emitted so far, scaled by powers of alpha. constraint_accs: Vec>, /// The evaluation of `X - g^(n-1)`. z_last: ExtensionTarget, /// The evaluation of the Lagrange basis polynomial which is nonzero at the point associated /// with the first trace row, and zero at other points in the subgroup. lagrange_basis_first: ExtensionTarget, /// The evaluation of the Lagrange basis polynomial which is nonzero at the point associated /// with the last trace row, and zero at other points in the subgroup. lagrange_basis_last: ExtensionTarget, _phantom: PhantomData, } impl, const D: usize> RecursiveConstraintConsumer { pub fn new( zero: ExtensionTarget, alphas: Vec, z_last: ExtensionTarget, lagrange_basis_first: ExtensionTarget, lagrange_basis_last: ExtensionTarget, ) -> Self { Self { constraint_accs: vec![zero; alphas.len()], alphas, z_last, lagrange_basis_first, lagrange_basis_last, _phantom: Default::default(), } } pub fn accumulators(self) -> Vec> { self.constraint_accs } /// Add one constraint valid on all rows except the last. pub fn constraint_transition( &mut self, builder: &mut CircuitBuilder, constraint: ExtensionTarget, ) { let filtered_constraint = builder.mul_extension(constraint, self.z_last); self.constraint(builder, filtered_constraint); } /// Add one constraint valid on all rows. pub fn constraint( &mut self, builder: &mut CircuitBuilder, constraint: ExtensionTarget, ) { for (&alpha, acc) in self.alphas.iter().zip(&mut self.constraint_accs) { *acc = builder.scalar_mul_add_extension(alpha, *acc, constraint); } } /// Add one constraint, but first multiply it by a filter such that it will only apply to the /// first row of the trace. pub fn constraint_first_row( &mut self, builder: &mut CircuitBuilder, constraint: ExtensionTarget, ) { let filtered_constraint = builder.mul_extension(constraint, self.lagrange_basis_first); self.constraint(builder, filtered_constraint); } /// Add one constraint, but first multiply it by a filter such that it will only apply to the /// last row of the trace. pub fn constraint_last_row( &mut self, builder: &mut CircuitBuilder, constraint: ExtensionTarget, ) { let filtered_constraint = builder.mul_extension(constraint, self.lagrange_basis_last); self.constraint(builder, filtered_constraint); } }