fullcodec_plonk/constraint_system/
constraint.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4//
5// Copyright (c) DUSK NETWORK. All rights reserved.
6
7use crate::constraint_system::{TurboComposer, Witness};
8use dusk_bls12_381::BlsScalar;
9
10/// Selectors used to address a coefficient inside of a [`Constraint`]
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub(crate) enum Selector {
13    /// Multiplication coefficient `q_m`
14    Multiplication = 0x00,
15    /// Left coefficient `q_l`
16    Left = 0x01,
17    /// Right coefficient `q_r`
18    Right = 0x02,
19    /// Output coefficient `q_o`
20    Output = 0x03,
21    /// Fourth advice coefficient `q_4`
22    Fourth = 0x04,
23    /// Constant expression `q_c`
24    Constant = 0x05,
25    /// Public input `pi`
26    PublicInput = 0x06,
27
28    /// Arithmetic coefficient (internal use)
29    Arithmetic = 0x07,
30    /// Range coefficient (internal use)
31    Range = 0x08,
32    /// Logic coefficient (internal use)
33    Logic = 0x09,
34    /// Curve addition with fixed base coefficient (internal use)
35    GroupAddFixedBase = 0x0a,
36    /// Curve addition with variable base coefficient (internal use)
37    GroupAddVariableBase = 0x0b,
38    /// Lookup coefficient (internal use)
39    Lookup = 0x0c,
40}
41
42/// Wire used to address a witness inside of a [`Constraint`]
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub(crate) enum WiredWitness {
45    /// `A` witness
46    A = 0x00,
47    /// `B` witness
48    B = 0x01,
49    /// `O` witness
50    O = 0x02,
51    /// `D` witness
52    D = 0x03,
53}
54
55/// Constraint representation containing the coefficients of a polynomial
56/// evaluation
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub struct Constraint {
59    coefficients: [BlsScalar; 13],
60    witnesses: [Witness; 4],
61
62    // TODO Workaround solution to keep the sparse public input indexes in the
63    // composer
64    //
65    // The indexes are needed to build the `VerifierData` so it won't contain
66    // all the constraints of the circuit.
67    //
68    // However, the composer uses a dense instance of the public inputs to
69    // prove statements. This way, it will need to keep the vector of
70    // indexes internally so the `VerifierData` can be properly generated.
71    //
72    // Whenever `Constraint::public` is called and appended to a composer, the
73    // composer must include this constraint index into the sparse set of
74    // public input indexes.
75    //
76    // This workaround can be removed only after the composer replaces the
77    // internal `Vec<BlsScalar>` of the selectors by a single
78    // `Vec<Constraint>`.
79    //
80    // Related issue: https://github.com/dusk-network/plonk/issues/607
81    has_public_input: bool,
82}
83
84impl Default for Constraint {
85    fn default() -> Self {
86        Self::new()
87    }
88}
89
90impl AsRef<[BlsScalar]> for Constraint {
91    fn as_ref(&self) -> &[BlsScalar] {
92        &self.coefficients
93    }
94}
95
96impl Constraint {
97    /// Initiate the composition of a new selector description of a circuit.
98    pub const fn new() -> Self {
99        Self {
100            coefficients: [BlsScalar::zero(); 13],
101            witnesses: [TurboComposer::constant_zero(); 4],
102            has_public_input: false,
103        }
104    }
105
106    fn set<T: Into<BlsScalar>>(mut self, r: Selector, s: T) -> Self {
107        self.coefficients[r as usize] = s.into();
108
109        self
110    }
111
112    fn from_external(constraint: &Self) -> Self {
113        const EXTERNAL: usize = Selector::Arithmetic as usize;
114
115        let mut s = Self::default();
116
117        let src = &constraint.coefficients[..EXTERNAL];
118        let dst = &mut s.coefficients[..EXTERNAL];
119
120        dst.copy_from_slice(src);
121
122        s.has_public_input = constraint.has_public_input();
123        s.witnesses.copy_from_slice(&constraint.witnesses);
124
125        s
126    }
127
128    /// Return a reference to the specified selector of a circuit constraint.
129    pub(crate) const fn coeff(&self, r: Selector) -> &BlsScalar {
130        &self.coefficients[r as usize]
131    }
132
133    /// Return the wired witness in the constraint
134    pub(crate) const fn witness(&self, w: WiredWitness) -> Witness {
135        self.witnesses[w as usize]
136    }
137
138    /// Set `s` as the polynomial selector for the multiplication coefficient.
139    pub fn mult<T: Into<BlsScalar>>(self, s: T) -> Self {
140        self.set(Selector::Multiplication, s)
141    }
142
143    /// Set `s` as the polynomial selector for the left coefficient.
144    pub fn left<T: Into<BlsScalar>>(self, s: T) -> Self {
145        self.set(Selector::Left, s)
146    }
147
148    /// Set `s` as the polynomial selector for the right coefficient.
149    pub fn right<T: Into<BlsScalar>>(self, s: T) -> Self {
150        self.set(Selector::Right, s)
151    }
152
153    /// Set `s` as the polynomial selector for the output coefficient.
154    pub fn output<T: Into<BlsScalar>>(self, s: T) -> Self {
155        self.set(Selector::Output, s)
156    }
157
158    /// Set `s` as the polynomial selector for the fourth (advice) coefficient.
159    pub fn fourth<T: Into<BlsScalar>>(self, s: T) -> Self {
160        self.set(Selector::Fourth, s)
161    }
162
163    /// Set `s` as the polynomial selector for the constant of the constraint.
164    pub fn constant<T: Into<BlsScalar>>(self, s: T) -> Self {
165        self.set(Selector::Constant, s)
166    }
167
168    /// Set `s` as the public input of the constraint evaluation.
169    pub fn public<T: Into<BlsScalar>>(mut self, s: T) -> Self {
170        self.has_public_input = true;
171
172        self.set(Selector::PublicInput, s)
173    }
174
175    /// Set witness `a` wired to `qM` and `qL`
176    pub fn a(mut self, w: Witness) -> Self {
177        self.witnesses[WiredWitness::A as usize] = w;
178
179        self
180    }
181
182    /// Set witness `b` wired to `qM` and `qR`
183    pub fn b(mut self, w: Witness) -> Self {
184        self.witnesses[WiredWitness::B as usize] = w;
185
186        self
187    }
188
189    /// Set witness `o` wired to `qO`
190    pub fn o(mut self, w: Witness) -> Self {
191        self.witnesses[WiredWitness::O as usize] = w;
192
193        self
194    }
195
196    /// Set witness `d` wired to the fourth/advice `q4` coefficient
197    pub fn d(mut self, w: Witness) -> Self {
198        self.witnesses[WiredWitness::D as usize] = w;
199
200        self
201    }
202
203    pub(crate) const fn has_public_input(&self) -> bool {
204        self.has_public_input
205    }
206
207    pub(crate) fn arithmetic(s: &Self) -> Self {
208        Self::from_external(s).set(Selector::Arithmetic, 1)
209    }
210
211    #[allow(dead_code)]
212    // TODO to be used when `TurboComposer` replaces internal selectors with
213    // this struct
214    pub(crate) fn range(s: &Self) -> Self {
215        Self::from_external(s).set(Selector::Range, 1)
216    }
217
218    #[allow(dead_code)]
219    // TODO to be used when `TurboComposer` replaces internal selectors with
220    // this struct
221    pub(crate) fn logic(s: &Self) -> Self {
222        Self::from_external(s)
223            .set(Selector::Constant, 1)
224            .set(Selector::Logic, 1)
225    }
226
227    #[allow(dead_code)]
228    // TODO to be used when `TurboComposer` replaces internal selectors with
229    // this struct
230    pub(crate) fn logic_xor(s: &Self) -> Self {
231        Self::from_external(s)
232            .set(Selector::Constant, -BlsScalar::one())
233            .set(Selector::Logic, -BlsScalar::one())
234    }
235
236    #[allow(dead_code)]
237    // TODO to be used when `TurboComposer` replaces internal selectors with
238    // this struct
239    pub(crate) fn group_add_fixed_base(s: &Self) -> Self {
240        Self::from_external(s).set(Selector::GroupAddFixedBase, 1)
241    }
242
243    #[allow(dead_code)]
244    // TODO to be used when `TurboComposer` replaces internal selectors with
245    // this struct
246    pub(crate) fn group_add_variable_base(s: &Self) -> Self {
247        Self::from_external(s).set(Selector::GroupAddVariableBase, 1)
248    }
249
250    #[allow(dead_code)]
251    // TODO to be used when `TurboComposer` replaces internal selectors with
252    // this struct
253    pub(crate) fn lookup(s: &Self) -> Self {
254        Self::from_external(s).set(Selector::Lookup, 1)
255    }
256}