kimchi/circuits/polynomials/foreign_field_mul/
gadget.rs

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