Skip to main content

kimchi/circuits/polynomials/foreign_field_mul/
gadget.rs

1//! This module obtains the gates of a foreign field addition circuit.
2use alloc::{vec, vec::Vec};
3
4use ark_ff::PrimeField;
5use num_bigint::BigUint;
6use o1_utils::foreign_field::ForeignFieldHelpers;
7
8use crate::{
9    alphas::Alphas,
10    circuits::{
11        argument::Argument,
12        berkeley_columns::E,
13        expr::Cache,
14        gate::{CircuitGate, GateType},
15        lookup::{
16            self,
17            tables::{GateLookupTable, LookupTable},
18        },
19        polynomials::{
20            foreign_field_common::{BigUintForeignFieldHelpers, KimchiForeignElement},
21            generic::GenericGateSpec,
22        },
23        wires::Wire,
24    },
25};
26
27use super::circuitgates::ForeignFieldMul;
28
29/// Number of gates in this gadget
30pub const GATE_COUNT: usize = 1;
31
32impl<F: PrimeField> CircuitGate<F> {
33    /// Create foreign field multiplication gate
34    ///     Inputs the starting row
35    ///     Outputs tuple (next_row, circuit_gates) where
36    ///       next_row      - next row after this gate
37    ///       circuit_gates - vector of circuit gates comprising this gate
38    pub fn create_foreign_field_mul(
39        start_row: usize,
40        foreign_field_modulus: &BigUint,
41    ) -> (usize, Vec<Self>) {
42        let neg_foreign_field_modulus = foreign_field_modulus.negate().to_field_limbs::<F>();
43        let foreign_field_modulus = foreign_field_modulus.to_field_limbs::<F>();
44        let circuit_gates = vec![
45            CircuitGate {
46                typ: GateType::ForeignFieldMul,
47                wires: Wire::for_row(start_row),
48                coeffs: vec![
49                    foreign_field_modulus[2],
50                    neg_foreign_field_modulus[0],
51                    neg_foreign_field_modulus[1],
52                    neg_foreign_field_modulus[2],
53                ],
54            },
55            CircuitGate {
56                typ: GateType::Zero,
57                wires: Wire::for_row(start_row + 1),
58                coeffs: vec![],
59            },
60        ];
61
62        (start_row + circuit_gates.len(), circuit_gates)
63    }
64
65    /// Create foreign field multiplication gate by extending the existing gates
66    pub fn extend_foreign_field_mul(
67        gates: &mut Vec<Self>,
68        curr_row: &mut usize,
69        foreign_field_modulus: &BigUint,
70    ) {
71        let (next_row, circuit_gates) =
72            Self::create_foreign_field_mul(*curr_row, foreign_field_modulus);
73        *curr_row = next_row;
74        gates.extend_from_slice(&circuit_gates);
75    }
76
77    pub fn extend_high_bounds(
78        gates: &mut Vec<Self>,
79        curr_row: &mut usize,
80        foreign_field_modulus: &BigUint,
81    ) {
82        let r = gates.len();
83        let hi_fmod = foreign_field_modulus.to_field_limbs::<F>()[2];
84        let hi_limb: F = KimchiForeignElement::<F>::two_to_limb() - hi_fmod - F::one();
85        let g = GenericGateSpec::Plus(hi_limb);
86        CircuitGate::extend_generic(gates, curr_row, Wire::for_row(r), g.clone(), Some(g));
87    }
88}
89
90// TODO: Check do we use this anywhere
91pub fn circuit_gate_selector_index(typ: GateType) -> usize {
92    match typ {
93        GateType::ForeignFieldMul => 0,
94        _ => panic!("invalid gate type"),
95    }
96}
97
98/// Get vector of foreign field multiplication circuit gate types
99pub fn circuit_gates() -> [GateType; GATE_COUNT] {
100    [GateType::ForeignFieldMul]
101}
102
103/// Get combined constraints for a given foreign field multiplication circuit gate
104pub fn circuit_gate_constraints<F: PrimeField>(
105    typ: GateType,
106    alphas: &Alphas<F>,
107    cache: &mut Cache,
108) -> E<F> {
109    match typ {
110        GateType::ForeignFieldMul => ForeignFieldMul::combined_constraints(alphas, cache),
111        _ => panic!("invalid gate type"),
112    }
113}
114
115/// Number of constraints for a given foreign field mul circuit gate type
116pub fn circuit_gate_constraint_count<F: PrimeField>(typ: GateType) -> u32 {
117    match typ {
118        GateType::ForeignFieldMul => ForeignFieldMul::<F>::CONSTRAINTS,
119        _ => panic!("invalid gate type"),
120    }
121}
122
123/// Get the combined constraints for all foreign field multiplication circuit gates
124pub fn combined_constraints<F: PrimeField>(alphas: &Alphas<F>, cache: &mut Cache) -> E<F> {
125    ForeignFieldMul::combined_constraints(alphas, cache)
126}
127
128/// Get the foreign field multiplication lookup table
129pub fn lookup_table<F: PrimeField>() -> LookupTable<F> {
130    lookup::tables::get_table::<F>(GateLookupTable::RangeCheck)
131}