winter_air/air/boundary/constraint_group.rs
1// Copyright (c) Facebook, Inc. and its affiliates.
2//
3// This source code is licensed under the MIT license found in the
4// LICENSE file in the root directory of this source tree.
5
6use alloc::{collections::BTreeMap, vec::Vec};
7
8use super::{Assertion, BoundaryConstraint, ConstraintDivisor, ExtensionOf, FieldElement};
9
10// BOUNDARY CONSTRAINT GROUP
11// ================================================================================================
12/// A group of boundary constraints all having the same divisor.
13///
14/// A boundary constraint is described by a rational function $\frac{f(x) - b(x)}{z(x)}$, where:
15///
16/// * $f(x)$ is a trace polynomial for the column against which the constraint is placed.
17/// * $b(x)$ is the value polynomial for the constraint.
18/// * $z(x)$ is the constraint divisor polynomial.
19///
20/// A boundary constraint group groups together all boundary constraints where polynomial $z$ is
21/// the same. The constraints stored in the group describe polynomials $b$. At the time of
22/// constraint evaluation, a prover or a verifier provides evaluations of the relevant polynomial
23/// $f$ so that the value of the constraint can be computed.
24///
25/// When the protocol is run in a large field, types `F` and `E` are the same. However, when
26/// working with small fields, `F` and `E` can be set as follows:
27/// * `F` could be the base field of the protocol, in which case `E` is the extension field used.
28/// * `F` could be the extension field, in which case `F` and `E` are the same type.
29///
30/// The above arrangement allows us to describe boundary constraints for main and auxiliary
31/// segments of the execution trace. Specifically:
32/// * For the constraints against columns of the main execution trace, `F` is set to the base field
33/// of the protocol, and `E` is set to the extension field.
34/// * For the constraints against columns of the auxiliary trace segment, both `F` and `E` are set
35/// to the extension field.
36#[derive(Debug, Clone)]
37pub struct BoundaryConstraintGroup<F, E>
38where
39 F: FieldElement,
40 E: FieldElement<BaseField = F::BaseField> + ExtensionOf<F>,
41{
42 constraints: Vec<BoundaryConstraint<F, E>>,
43 divisor: ConstraintDivisor<F::BaseField>,
44}
45
46impl<F, E> BoundaryConstraintGroup<F, E>
47where
48 F: FieldElement,
49 E: FieldElement<BaseField = F::BaseField> + ExtensionOf<F>,
50{
51 // CONSTRUCTOR
52 // --------------------------------------------------------------------------------------------
53 /// Returns a new boundary constraint group to hold constraints with the specified divisor.
54 pub(super) fn new(divisor: ConstraintDivisor<F::BaseField>) -> Self {
55 BoundaryConstraintGroup { constraints: Vec::new(), divisor }
56 }
57
58 // PUBLIC ACCESSORS
59 // --------------------------------------------------------------------------------------------
60
61 /// Returns a list of boundary constraints in this group.
62 pub fn constraints(&self) -> &[BoundaryConstraint<F, E>] {
63 &self.constraints
64 }
65
66 /// Returns a divisor applicable to all boundary constraints in this group.
67 pub fn divisor(&self) -> &ConstraintDivisor<F::BaseField> {
68 &self.divisor
69 }
70
71 // PUBLIC METHODS
72 // --------------------------------------------------------------------------------------------
73
74 /// Creates a new boundary constraint from the specified assertion and adds it to the group.
75 pub(super) fn add(
76 &mut self,
77 assertion: Assertion<F>,
78 inv_g: F::BaseField,
79 twiddle_map: &mut BTreeMap<usize, Vec<F::BaseField>>,
80 composition_coefficients: E,
81 ) {
82 self.constraints.push(BoundaryConstraint::new(
83 assertion,
84 inv_g,
85 twiddle_map,
86 composition_coefficients,
87 ));
88 }
89
90 /// Evaluates all constraints in this group at the specified point `x`.
91 ///
92 /// Constraint evaluations are merges into a single value by computing their random linear
93 /// combination and dividing the result by the divisor of this constraint group as follows:
94 /// $$
95 /// \frac{\sum_{i=0}^{k-1}{\alpha_i \cdot C_i(x)}}{z(x)}
96 /// $$
97 /// where:
98 /// * $C_i(x)$ is the evaluation of the $i$th constraint at `x` computed as $f(x) - b(x)$.
99 /// * $\alpha_i$ are random field elements. In the interactive version of the protocol, these
100 /// are provided by the verifier.
101 pub fn evaluate_at(&self, state: &[E], x: E) -> E {
102 let mut numerator = E::ZERO;
103 for constraint in self.constraints().iter() {
104 let trace_value = state[constraint.column()];
105 let evaluation = constraint.evaluate_at(x, trace_value);
106 numerator += evaluation * *constraint.cc();
107 }
108
109 let denominator = self.divisor.evaluate_at(x);
110
111 numerator / denominator
112 }
113}