Fix the pedantic lints (5)
MODIFY
kimchi/src/circuits/expr.rs
kimchi/src/circuits/expr.rs
@@ -1618,6 +1618,7 @@ impl<F: Neg<Output = F> + Clone + One + Zero + PartialEq> Expr<F> {
// is called repeatedly in monomials, yielding quadratic behavior for
// that function. It's ok for now as we only call that function once on
// a small input when producing the verification key.
+ #[allow(clippy::match_same_arms)]
fn is_constant(&self, evaluated: &HashSet<Column>) -> bool {
use Expr::*;
match self {
@@ -1640,7 +1641,10 @@ impl<F: Neg<Output = F> + Clone + One + Zero + PartialEq> Expr<F> {
h
};
let constant = |e: Expr<F>| sing(vec![], e);
- use Expr::*;
+ use Expr::{
+ BinOp, Cache, Cell, Constant, Double, Pow, Square, UnnormalizedLagrangeBasis,
+ VanishesOnLast4Rows,
+ };
if self.is_constant(ev) {
return constant(self.clone());
@@ -1735,6 +1739,7 @@ impl<F: Neg<Output = F> + Clone + One + Zero + PartialEq> Expr<F> {
/// this function computes `lin_or_err(factor_{V_0}(e))`, although it does not
/// compute it in that way. Instead, it computes it by reducing the expression into
/// a sum of monomials with `F` coefficients, and then factors the monomials.
+ #[allow(clippy::needless_pass_by_value)]
pub fn linearize(
&self,
evaluated: HashSet<Column>,
@@ -1827,7 +1832,7 @@ impl<F: One + Neg<Output = F>> Neg for ConstantExpr<F> {
impl<F: Field> Add<ConstantExpr<F>> for ConstantExpr<F> {
type Output = ConstantExpr<F>;
fn add(self, other: Self) -> Self {
- use ConstantExpr::*;
+ use ConstantExpr::{Add, Literal};
if self.is_zero() {
return other;
}
@@ -1844,7 +1849,7 @@ impl<F: Field> Add<ConstantExpr<F>> for ConstantExpr<F> {
impl<F: Field> Sub<ConstantExpr<F>> for ConstantExpr<F> {
type Output = ConstantExpr<F>;
fn sub(self, other: Self) -> Self {
- use ConstantExpr::*;
+ use ConstantExpr::{Literal, Sub};
if other.is_zero() {
return self;
}
@@ -1858,7 +1863,7 @@ impl<F: Field> Sub<ConstantExpr<F>> for ConstantExpr<F> {
impl<F: Field> Mul<ConstantExpr<F>> for ConstantExpr<F> {
type Output = ConstantExpr<F>;
fn mul(self, other: Self) -> Self {
- use ConstantExpr::*;
+ use ConstantExpr::{Literal, Mul};
if self.is_one() {
return other;
}
@@ -1931,7 +1936,7 @@ impl<F: Zero + Clone> AddAssign<Expr<F>> for Expr<F> {
if self.is_zero() {
*self = other;
} else if !other.is_zero() {
- *self = Expr::BinOp(Op2::Add, Box::new(self.clone()), Box::new(other))
+ *self = Expr::BinOp(Op2::Add, Box::new(self.clone()), Box::new(other));
}
}
}
@@ -2010,7 +2015,9 @@ impl<F: Field> Mul<F> for Expr<ConstantExpr<F>> {
impl<F: PrimeField> ConstantExpr<F> {
fn ocaml(&self) -> String {
- use ConstantExpr::*;
+ use ConstantExpr::{
+ Add, Alpha, Beta, EndoCoefficient, Gamma, JointCombiner, Literal, Mds, Mul, Pow, Sub,
+ };
match self {
Alpha => "alpha".to_string(),
Beta => "beta".to_string(),
@@ -2030,7 +2037,9 @@ impl<F: PrimeField> ConstantExpr<F> {
}
fn latex(&self) -> String {
- use ConstantExpr::*;
+ use ConstantExpr::{
+ Add, Alpha, Beta, EndoCoefficient, Gamma, JointCombiner, Literal, Mds, Mul, Pow, Sub,
+ };
match self {
Alpha => "\\alpha".to_string(),
Beta => "\\beta".to_string(),
@@ -2065,7 +2074,7 @@ where
env.sort_by(|(x, _), (y, _)| x.cmp(y));
let mut res = String::new();
- for (k, v) in env.into_iter() {
+ for (k, v) in env {
let rhs = v.ocaml_str();
let cached = format!("let {} = {rhs} in ", k.var_name());
res.push_str(&cached);
@@ -2078,7 +2087,10 @@ where
/// Recursively print the expression,
/// except for the cached expression that are stored in the `cache`.
fn ocaml(&self, cache: &mut HashMap<CacheId, Expr<ConstantExpr<F>>>) -> String {
- use Expr::*;
+ use Expr::{
+ BinOp, Cache, Cell, Constant, Double, Pow, Square, UnnormalizedLagrangeBasis,
+ VanishesOnLast4Rows,
+ };
match self {
Double(x) => format!("double({})", x.ocaml(cache)),
Constant(x) => x.ocaml(),
@@ -2108,7 +2120,7 @@ where
env.sort_by(|(x, _), (y, _)| x.cmp(y));
let mut res = vec![];
- for (k, v) in env.into_iter() {
+ for (k, v) in env {
let mut rhs = v.latex_str();
let last = rhs.pop().expect("returned an empty expression");
res.push(format!("{} = {last}", k.latex_name()));
@@ -2119,7 +2131,10 @@ where
}
fn latex(&self, cache: &mut HashMap<CacheId, Expr<ConstantExpr<F>>>) -> String {
- use Expr::*;
+ use Expr::{
+ BinOp, Cache, Cell, Constant, Double, Pow, Square, UnnormalizedLagrangeBasis,
+ VanishesOnLast4Rows,
+ };
match self {
Double(x) => format!("2 ({})", x.latex(cache)),
Constant(x) => x.latex(),
@@ -2168,12 +2183,15 @@ pub mod constraints {
Self: std::marker::Sized,
{
/// Double the value
+ #[must_use]
fn double(&self) -> Self;
/// Compute the square of this value
+ #[must_use]
fn square(&self) -> Self;
/// Raise the value to the given power
+ #[must_use]
fn pow(&self, p: u64) -> Self;
/// Constrain to boolean
@@ -2308,25 +2326,30 @@ pub fn constant<F>(x: F) -> E<F> {
}
/// Helper function to quickly create an expression for a witness.
+#[must_use]
pub fn witness<F>(i: usize, row: CurrOrNext) -> E<F> {
E::<F>::cell(Column::Witness(i), row)
}
/// Same as [witness] but for the current row.
+#[must_use]
pub fn witness_curr<F>(i: usize) -> E<F> {
witness(i, CurrOrNext::Curr)
}
/// Same as [witness] but for the next row.
+#[must_use]
pub fn witness_next<F>(i: usize) -> E<F> {
witness(i, CurrOrNext::Next)
}
/// Handy function to quickly create an expression for a gate.
+#[must_use]
pub fn index<F>(g: GateType) -> E<F> {
E::<F>::cell(Column::Index(g), CurrOrNext::Curr)
}
+#[must_use]
pub fn coeff<F>(i: usize) -> E<F> {
E::<F>::cell(Column::Coefficient(i), CurrOrNext::Curr)
}

MODIFY
kimchi/src/circuits/gate.rs
kimchi/src/circuits/gate.rs
@@ -43,6 +43,7 @@ impl CurrOrNext {
/// Compute the offset corresponding to the `CurrOrNext` value.
/// - `Curr.shift() == 0`
/// - `Next.shift() == 1`
+ #[must_use]
pub fn shift(&self) -> usize {
match self {
CurrOrNext::Curr => 0,
@@ -77,6 +78,7 @@ impl CurrOrNext {
)]
#[cfg_attr(feature = "wasm_types", wasm_bindgen::prelude::wasm_bindgen)]
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
+#[allow(clippy::module_name_repetitions)]
pub enum GateType {
/// Zero gate
Zero = 0,
@@ -160,6 +162,7 @@ pub type CircuitGateResult<T> = std::result::Result<T, CircuitGateError>;
#[serde_as]
#[derive(Clone, Debug, Serialize, Deserialize)]
+#[allow(clippy::module_name_repetitions)]
/// A single gate in a circuit.
pub struct CircuitGate<F: PrimeField> {
/// type of the gate
@@ -172,12 +175,13 @@ pub struct CircuitGate<F: PrimeField> {
}
impl<F: PrimeField> ToBytes for CircuitGate<F> {
+ #[allow(clippy::cast_possible_truncation)]
#[inline]
fn write<W: Write>(&self, mut w: W) -> IoResult<()> {
let typ: u8 = ToPrimitive::to_u8(&self.typ).unwrap();
typ.write(&mut w)?;
for i in 0..COLUMNS {
- self.wires[i].write(&mut w)?
+ self.wires[i].write(&mut w)?;
}
(self.coeffs.len() as u8).write(&mut w)?;
@@ -190,6 +194,7 @@ impl<F: PrimeField> ToBytes for CircuitGate<F> {
impl<F: PrimeField> CircuitGate<F> {
/// this function creates "empty" circuit gate
+ #[must_use]
pub fn zero(wires: GateWires) -> Self {
CircuitGate {
typ: GateType::Zero,
@@ -200,6 +205,11 @@ impl<F: PrimeField> CircuitGate<F> {
/// This function verifies the consistency of the wire
/// assignments (witness) against the constraints
+ ///
+ /// # Errors
+ ///
+ /// Will give error if verify process returns error.
+ #[allow(clippy::match_same_arms)]
pub fn verify<G: KimchiCurve<ScalarField = F>>(
&self,
row: usize,
@@ -207,7 +217,11 @@ impl<F: PrimeField> CircuitGate<F> {
cs: &ConstraintSystem<F>,
public: &[F],
) -> Result<(), String> {
- use GateType::*;
+ use GateType::{
+ CairoClaim, CairoFlags, CairoInstruction, CairoTransition, ChaCha0, ChaCha1, ChaCha2,
+ ChaChaFinal, CompleteAdd, EndoMul, EndoMulScalar, Generic, Lookup, Poseidon,
+ RangeCheck0, RangeCheck1, VarBaseMul, Zero,
+ };
match self.typ {
Zero => Ok(()),
Generic => self.verify_generic(row, witness, public),
@@ -353,7 +367,7 @@ impl<F: PrimeField> CircuitGate<F> {
/// Trait to connect a pair of cells in a circuit
pub trait Connect {
/// Connect the pair of cells specified by the cell1 and cell2 parameters
- /// cell_pre --> cell_new && cell_new --> wire_tmp
+ /// `cell_pre` --> `cell_new` && `cell_new` --> `wire_tmp`
///
/// Note: This function assumes that the targeted cells are freshly instantiated
/// with self-connections. If the two cells are transitively already part
@@ -369,7 +383,7 @@ impl<F: PrimeField> Connect for Vec<CircuitGate<F>> {
}
}
-/// A circuit is specified as a series of [CircuitGate].
+/// A circuit is specified as a series of [`CircuitGate`].
#[derive(Serialize)]
pub struct Circuit<'a, F: PrimeField>(
#[serde(bound = "CircuitGate<F>: Serialize")] pub &'a [CircuitGate<F>],
@@ -477,6 +491,8 @@ pub mod caml {
#[cfg(test)]
mod tests {
+ use crate::circuits::wires::PERMUTS;
+
use super::*;
use ark_ff::UniformRand as _;
use mina_curves::pasta::Fp;

MODIFY
kimchi/src/circuits/lookup/constraints.rs
kimchi/src/circuits/lookup/constraints.rs
use crate::{
circuits::{
- expr::{prologue::*, Column, ConstantExpr},
+ expr::{
+ prologue::{witness, E},
+ Column, ConstantExpr,
+ },
gate::{CircuitGate, CurrOrNext},
lookup::lookups::{
JointLookup, JointLookupSpec, JointLookupValue, LocalPosition, LookupInfo, LookupsUsed,
@@ -28,6 +31,10 @@ pub const ZK_ROWS: usize = 3;
/// Pad with zeroes and then add 3 random elements in the last two
/// rows for zero knowledge.
+///
+/// # Panics
+///
+/// Will panic if `evaluation` and `domain` length do not meet the requirement.
pub fn zk_patch<R: Rng + ?Sized, F: FftField>(
mut e: Vec<F>,
d: D<F>,
@@ -77,6 +84,10 @@ pub fn zk_patch<R: Rng + ?Sized, F: FftField>(
//~
/// Computes the sorted lookup tables required by the lookup argument.
+///
+/// # Panics
+///
+/// Will panic if `value(s)` are missing from the `table`.
#[allow(clippy::too_many_arguments)]
pub fn sorted<F: PrimeField>(
dummy_lookup_value: F,
@@ -214,7 +225,11 @@ pub fn sorted<F: PrimeField>(
///
/// after multiplying all of the values, all of the terms will have cancelled if s is a sorting of f and t, and the final term will be 1
/// because of the random choice of beta and gamma, there is negligible probability that the terms will cancel if s is not a sorting of f and t
-#[allow(clippy::too_many_arguments)]
+///
+/// # Panics
+///
+/// Will panic if final evaluation is not 1.
+#[allow(clippy::too_many_arguments, clippy::manual_assert)]
pub fn aggregation<R, F>(
dummy_lookup_value: F,
joint_lookup_table_d8: &Evaluations<F, D<F>>,
@@ -260,8 +275,8 @@ where
let complements_with_beta_term = {
let mut v = vec![F::one()];
let x = gamma + dummy_lookup_value;
- for i in 1..(max_lookups_per_row + 1) {
- v.push(v[i - 1] * x)
+ for i in 1..=max_lookups_per_row {
+ v.push(v[i - 1] * x);
}
let beta1_per_row = beta1.pow(&[max_lookups_per_row as u64]);
@@ -340,6 +355,11 @@ pub struct LookupConfiguration<F: FftField> {
}
/// Specifies the lookup constraints as expressions.
+///
+/// # Panics
+///
+/// Will panic if single `element` length is bigger than `max_per_row` length.
+#[allow(clippy::cast_possible_truncation, clippy::too_many_lines)]
pub fn constraints<F: FftField>(configuration: &LookupConfiguration<F>) -> Vec<E<F>> {
// Something important to keep in mind is that the last 2 rows of
// all columns will have random values in them to maintain zero-knowledge.
@@ -403,8 +423,8 @@ pub fn constraints<F: FftField>(configuration: &LookupConfiguration<F>) -> Vec<E
// v[i] = (gamma + dummy)^i
let mut dummies = vec![ConstantExpr::one()];
let dummy = ConstantExpr::Gamma + dummy_lookup;
- for i in 1..(lookup_info.max_per_row + 1) {
- dummies.push(dummies[i - 1].clone() * dummy.clone())
+ for i in 1..=lookup_info.max_per_row {
+ dummies.push(dummies[i - 1].clone() * dummy.clone());
}
// TODO: we can just multiply with (1+beta)^max_per_row at the end for any f_term, it feels weird to do it here
@@ -552,7 +572,11 @@ pub fn constraints<F: FftField>(configuration: &LookupConfiguration<F>) -> Vec<E
}
/// Checks that all the lookup constraints are satisfied.
-#[allow(clippy::too_many_arguments)]
+///
+/// # Panics
+///
+/// Will panic if `d1` and `s` domain sizes do not match.
+#[allow(clippy::too_many_arguments, clippy::manual_assert)]
pub fn verify<F: PrimeField, I: Iterator<Item = F>, TABLE: Fn() -> I>(
dummy_lookup_value: F,
lookup_table: TABLE,
@@ -587,9 +611,9 @@ pub fn verify<F: PrimeField, I: Iterator<Item = F>, TABLE: Fn() -> I>(
for (i, s) in sorted.iter().enumerate() {
let es = s.evals.iter().take(lookup_rows + 1);
if i % 2 == 0 {
- sorted_joined.extend(es)
+ sorted_joined.extend(es);
} else {
- sorted_joined.extend(es.rev())
+ sorted_joined.extend(es.rev());
}
}
@@ -609,11 +633,11 @@ pub fn verify<F: PrimeField, I: Iterator<Item = F>, TABLE: Fn() -> I>(
for (i, s) in sorted.iter().enumerate() {
if i % 2 == 0 {
for x in s.evals.iter().take(lookup_rows) {
- *counts.entry(*x).or_insert(0) += 1
+ *counts.entry(*x).or_insert(0) += 1;
}
} else {
for x in s.evals.iter().skip(1).take(lookup_rows) {
- *counts.entry(*x).or_insert(0) += 1
+ *counts.entry(*x).or_insert(0) += 1;
}
}
}
@@ -635,10 +659,10 @@ pub fn verify<F: PrimeField, I: Iterator<Item = F>, TABLE: Fn() -> I>(
for joint_lookup in spec.iter() {
let joint_lookup_evaluation =
joint_lookup.evaluate(joint_combiner, table_id_combiner, &eval);
- *all_lookups.entry(joint_lookup_evaluation).or_insert(0) += 1
+ *all_lookups.entry(joint_lookup_evaluation).or_insert(0) += 1;
}
- *all_lookups.entry(dummy_lookup_value).or_insert(0) += lookup_info.max_per_row - spec.len()
+ *all_lookups.entry(dummy_lookup_value).or_insert(0) += lookup_info.max_per_row - spec.len();
}
assert_eq!(

MODIFY
kimchi/src/circuits/lookup/index.rs
kimchi/src/circuits/lookup/index.rs
@@ -194,6 +194,12 @@ pub struct LookupConstraintSystem<F: FftField> {
}
impl<F: PrimeField + SquareRootField> LookupConstraintSystem<F> {
+ /// Create the `LookupConstraintSystem`.
+ ///
+ /// # Errors
+ ///
+ /// Will give error if inputs validation do not match.
+ #[allow(clippy::cast_possible_truncation, clippy::too_many_lines)]
pub fn create(
gates: &[CircuitGate<F>],
lookup_tables: Vec<LookupTable<F>>,
@@ -268,7 +274,7 @@ impl<F: PrimeField + SquareRootField> LookupConstraintSystem<F> {
// create fixed tables for indexing the runtime tables
for runtime_table in runtime_tables {
- use RuntimeTableCfg::*;
+ use RuntimeTableCfg::{Custom, Indexed};
let (id, first_column) = match runtime_table {
&Indexed(RuntimeTableSpec { id, len }) => {
let indexes = (0..(len as u32)).map(F::from).collect();
@@ -355,13 +361,13 @@ impl<F: PrimeField + SquareRootField> LookupConstraintSystem<F> {
for table in &lookup_tables {
let table_len = table.data[0].len();
- if table.id != 0 {
- non_zero_table_id = true;
- } else {
+ if table.id == 0 {
has_table_id_0 = true;
if table.has_zero_entry() {
has_table_id_0_with_zero_entry = true;
}
+ } else {
+ non_zero_table_id = true;
}
//~~ - Update the corresponding entries in a table id vector (of size the domain as well)
@@ -379,7 +385,7 @@ impl<F: PrimeField + SquareRootField> LookupConstraintSystem<F> {
//~~ - Fill in any unused columns with 0 (to match the dummy value)
for lookup_table in lookup_table.iter_mut().skip(table.data.len()) {
- lookup_table.extend(repeat_n(F::zero(), table_len))
+ lookup_table.extend(repeat_n(F::zero(), table_len));
}
}
@@ -415,7 +421,7 @@ impl<F: PrimeField + SquareRootField> LookupConstraintSystem<F> {
//~ 8. pre-compute polynomial and evaluation form for the look up tables
let mut lookup_table_polys: Vec<DP<F>> = vec![];
let mut lookup_table8: Vec<E<F, D<F>>> = vec![];
- for col in lookup_table.into_iter() {
+ for col in lookup_table {
let poly = E::<F, D<F>>::from_vec_and_domain(col, domain.d1).interpolate();
let eval = poly.evaluate_over_domain_by_ref(domain.d8);
lookup_table_polys.push(poly);

Fix the pedantic lints (5)