Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
non_native_field_relation.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Luke, Raju], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
10
11namespace bb {
12
31template <typename FF_> class NonNativeFieldRelationImpl {
32 public:
33 using FF = FF_;
34
35 static constexpr std::array<size_t, 1> SUBRELATION_PARTIAL_LENGTHS{
36 6 // combined non-native field sub-relation
37 };
38
43 template <typename AllEntities> inline static bool skip(const AllEntities& in) { return in.q_nnf.is_zero(); }
44
63 template <typename ContainerOverSubrelations, typename AllEntities, typename Parameters>
64 static void accumulate(ContainerOverSubrelations& accumulators,
65 const AllEntities& in,
66 BB_UNUSED const Parameters& params,
67 const FF& scaling_factor)
68 {
69 // all accumulators are of the same length, so we set our accumulator type to (arbitrarily) be the first one.
70 // if there were one that were shorter, we could also profitably use a `ShortAccumulator` type. however,
71 // that is not the case here.
72 using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>;
73 using CoefficientAccumulator = typename Accumulator::CoefficientAccumulator;
74
75 auto w_1_m = CoefficientAccumulator(in.w_l);
76 auto w_2_m = CoefficientAccumulator(in.w_r);
77 auto w_3_m = CoefficientAccumulator(in.w_o);
78 auto w_4_m = CoefficientAccumulator(in.w_4);
79 auto w_1_shift_m = CoefficientAccumulator(in.w_l_shift);
80 auto w_2_shift_m = CoefficientAccumulator(in.w_r_shift);
81 auto w_3_shift_m = CoefficientAccumulator(in.w_o_shift);
82 auto w_4_shift_m = CoefficientAccumulator(in.w_4_shift);
83
84 auto q_2_m = CoefficientAccumulator(in.q_r);
85 auto q_3_m = CoefficientAccumulator(in.q_o);
86 auto q_4_m = CoefficientAccumulator(in.q_4);
87 auto q_m_m = CoefficientAccumulator(in.q_m);
88
89 auto q_nnf_m = CoefficientAccumulator(in.q_nnf);
90 const FF LIMB_SIZE(uint256_t(1) << 68);
91 const FF SUBLIMB_SHIFT(uint256_t(1) << 14);
92
93 // Bigfield Product Gate 2 (selected by q_2 * q_4):
94 // Computes cross-term contributions in limb multiplication.
95 // Formula: (w_1 * w_2') + (w_1' * w_2) + (w_1 * w_4 + w_2 * w_3 - w_3') * 2^14 - w_3 - w_4' = 0
96 // where primed values (') denote shifted wires from the next row.
97 auto limb_subproduct = w_1_m * w_2_shift_m + w_1_shift_m * w_2_m;
98 auto non_native_field_gate_2_m = (w_1_m * w_4_m + w_2_m * w_3_m - w_3_shift_m);
99 non_native_field_gate_2_m *= LIMB_SIZE;
100 non_native_field_gate_2_m -= w_4_shift_m;
101 non_native_field_gate_2_m += limb_subproduct;
102 auto non_native_field_gate_2 = Accumulator(non_native_field_gate_2_m) * Accumulator(q_4_m);
103
104 // Bigfield Product Gate 1 (selected by q_2 * q_3):
105 // Accumulates limb products with 2^68 scaling for high-order terms.
106 // Formula: (w_1 * w_2') + (w_1' * w_2) * 2^68 + (w_1' * w_2') - w_3 - w_4 = 0
107 limb_subproduct *= LIMB_SIZE;
108 limb_subproduct += (w_1_shift_m * w_2_shift_m);
109 auto non_native_field_gate_1_m = limb_subproduct;
110 non_native_field_gate_1_m -= (w_3_m + w_4_m);
111 // Transform to Accumulator for degree > 2 (CoefficientAccumulator limited to degree 2)
112 auto non_native_field_gate_1 = Accumulator(non_native_field_gate_1_m) * Accumulator(q_3_m);
113
114 // Bigfield Product Gate 3 (selected by q_2 * q_m):
115 // Handles remaining cross-terms in the limb product expansion.
116 // Formula: limb_subproduct + w_4 - w_3' - w_4' = 0
117 auto non_native_field_gate_3_m = limb_subproduct;
118 non_native_field_gate_3_m += w_4_m;
119 non_native_field_gate_3_m -= (w_3_shift_m + w_4_shift_m);
120 auto non_native_field_gate_3 = Accumulator(non_native_field_gate_3_m) * Accumulator(q_m_m);
121
122 auto non_native_field_identity = non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3;
123 non_native_field_identity *= Accumulator(q_2_m);
124
125 // Limb Accumulation Gate 1 (selected by q_3 * q_4):
126 // Reconstructs a 68-bit limb from five 14-bit sublimbs stored across wires.
127 // Constraint: w_2' * 2^56 + w_1' * 2^42 + w_3 * 2^28 + w_2 * 2^14 + w_1 - w_4 = 0
128 // Horner form: ((((w_2' * 2^14 + w_1') * 2^14 + w_3) * 2^14 + w_2) * 2^14 + w_1) - w_4 = 0
129 auto limb_accumulator_1_m = w_2_shift_m * SUBLIMB_SHIFT;
130 limb_accumulator_1_m += w_1_shift_m;
131 limb_accumulator_1_m *= SUBLIMB_SHIFT;
132 limb_accumulator_1_m += w_3_m;
133 limb_accumulator_1_m *= SUBLIMB_SHIFT;
134 limb_accumulator_1_m += w_2_m;
135 limb_accumulator_1_m *= SUBLIMB_SHIFT;
136 limb_accumulator_1_m += w_1_m;
137 limb_accumulator_1_m -= w_4_m;
138 auto limb_accumulator_1_m_full = limb_accumulator_1_m * q_4_m;
139
140 // Limb Accumulation Gate 2 (selected by q_3 * q_m):
141 // Reconstructs a second 68-bit limb from five 14-bit sublimbs.
142 // Constraint: w_3' * 2^56 + w_2' * 2^42 + w_1' * 2^28 + w_4 * 2^14 + w_3 - w_4' = 0
143 // Horner form: ((((w_3' * 2^14 + w_2') * 2^14 + w_1') * 2^14 + w_4) * 2^14 + w_3) - w_4' = 0
144 auto limb_accumulator_2_m = w_3_shift_m * SUBLIMB_SHIFT;
145 limb_accumulator_2_m += w_2_shift_m;
146 limb_accumulator_2_m *= SUBLIMB_SHIFT;
147 limb_accumulator_2_m += w_1_shift_m;
148 limb_accumulator_2_m *= SUBLIMB_SHIFT;
149 limb_accumulator_2_m += w_4_m;
150 limb_accumulator_2_m *= SUBLIMB_SHIFT;
151 limb_accumulator_2_m += w_3_m;
152 limb_accumulator_2_m -= w_4_shift_m;
153 auto limb_accumulator_2_m_full = limb_accumulator_2_m * q_m_m;
154
155 auto limb_accumulator_identity_m = limb_accumulator_1_m_full + limb_accumulator_2_m_full;
156 Accumulator limb_accumulator_identity(limb_accumulator_identity_m);
157 limb_accumulator_identity *= q_3_m; // deg 3
158
159 auto q_nnf_by_scaling_m = q_nnf_m * scaling_factor; // deg 1
160 auto q_nnf_by_scaling = Accumulator(q_nnf_by_scaling_m);
161
162 auto nnf_identity = non_native_field_identity + limb_accumulator_identity;
163 nnf_identity *= q_nnf_by_scaling; // deg
164 std::get<0>(accumulators) += nnf_identity; // deg
165 };
166};
167
169} // namespace bb
Non-Native Field Relation for emulating arithmetic over fields larger than the native circuit field.
static bool skip(const AllEntities &in)
Returns true if the contribution from all subrelations for the provided inputs is identically zero.
static constexpr std::array< size_t, 1 > SUBRELATION_PARTIAL_LENGTHS
static void accumulate(ContainerOverSubrelations &accumulators, const AllEntities &in, BB_UNUSED const Parameters &params, const FF &scaling_factor)
Accumulates constraints for non-native field multiplication and limb decomposition.
A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the contribu...
#define BB_UNUSED
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13