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)
44 {
45 return in[AllEntities::EntityId::q_nnf].is_zero();
46 }
47
66 template <typename ContainerOverSubrelations, typename AllEntities, typename Parameters>
67 static void accumulate(ContainerOverSubrelations& accumulators,
68 const AllEntities& in,
69 BB_UNUSED const Parameters& params,
70 const FF& scaling_factor)
71 {
72 // all accumulators are of the same length, so we set our accumulator type to (arbitrarily) be the first one.
73 // if there were one that were shorter, we could also profitably use a `ShortAccumulator` type. however,
74 // that is not the case here.
76 using CoefficientAccumulator = typename Accumulator::CoefficientAccumulator;
77
78 auto w_1_m = CoefficientAccumulator(in[AllEntities::EntityId::w_l]);
79 auto w_2_m = CoefficientAccumulator(in[AllEntities::EntityId::w_r]);
80 auto w_3_m = CoefficientAccumulator(in[AllEntities::EntityId::w_o]);
81 auto w_4_m = CoefficientAccumulator(in[AllEntities::EntityId::w_4]);
82 auto w_1_shift_m = CoefficientAccumulator(in[AllEntities::EntityId::w_l_shift]);
83 auto w_2_shift_m = CoefficientAccumulator(in[AllEntities::EntityId::w_r_shift]);
84 auto w_3_shift_m = CoefficientAccumulator(in[AllEntities::EntityId::w_o_shift]);
85 auto w_4_shift_m = CoefficientAccumulator(in[AllEntities::EntityId::w_4_shift]);
86
87 auto q_2_m = CoefficientAccumulator(in[AllEntities::EntityId::q_r]);
88 auto q_3_m = CoefficientAccumulator(in[AllEntities::EntityId::q_o]);
89 auto q_4_m = CoefficientAccumulator(in[AllEntities::EntityId::q_4]);
90 auto q_m_m = CoefficientAccumulator(in[AllEntities::EntityId::q_m]);
91
92 auto q_nnf_m = CoefficientAccumulator(in[AllEntities::EntityId::q_nnf]);
93 const FF LIMB_SIZE(uint256_t(1) << 68);
94 const FF SUBLIMB_SHIFT(uint256_t(1) << 14);
95
96 // Bigfield Product Gate 2 (selected by q_2 * q_4):
97 // Computes cross-term contributions in limb multiplication.
98 // Formula: (w_1 * w_2') + (w_1' * w_2) + (w_1 * w_4 + w_2 * w_3 - w_3') * 2^68 - w_4' = 0
99 // where primed values (') denote shifted wires from the next row.
100 auto limb_subproduct = w_1_m * w_2_shift_m + w_1_shift_m * w_2_m;
101 auto non_native_field_gate_2_m = (w_1_m * w_4_m + w_2_m * w_3_m - w_3_shift_m);
102 non_native_field_gate_2_m *= LIMB_SIZE;
103 non_native_field_gate_2_m -= w_4_shift_m;
104 non_native_field_gate_2_m += limb_subproduct;
105 auto non_native_field_gate_2 = Accumulator(non_native_field_gate_2_m) * Accumulator(q_4_m);
106
107 // Bigfield Product Gate 1 (selected by q_2 * q_3):
108 // Accumulates limb products with 2^68 scaling for high-order terms.
109 // Formula: (w_1 * w_2' + w_1' * w_2) * 2^68 + (w_1' * w_2') - w_3 - w_4 = 0
110 limb_subproduct *= LIMB_SIZE;
111 limb_subproduct += (w_1_shift_m * w_2_shift_m);
112 auto non_native_field_gate_1_m = limb_subproduct;
113 non_native_field_gate_1_m -= (w_3_m + w_4_m);
114 // Transform to Accumulator for degree > 2 (CoefficientAccumulator limited to degree 2)
115 auto non_native_field_gate_1 = Accumulator(non_native_field_gate_1_m) * Accumulator(q_3_m);
116
117 // Bigfield Product Gate 3 (selected by q_2 * q_m):
118 // Handles remaining cross-terms in the limb product expansion.
119 // Formula: limb_subproduct + w_4 - w_3' - w_4' = 0
120 auto non_native_field_gate_3_m = limb_subproduct;
121 non_native_field_gate_3_m += w_4_m;
122 non_native_field_gate_3_m -= (w_3_shift_m + w_4_shift_m);
123 auto non_native_field_gate_3 = Accumulator(non_native_field_gate_3_m) * Accumulator(q_m_m);
124
125 auto non_native_field_identity = non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3;
126 non_native_field_identity *= Accumulator(q_2_m);
127
128 // Limb Accumulation Gate 1 (selected by q_3 * q_4):
129 // Reconstructs a 68-bit limb from five 14-bit sublimbs stored across wires.
130 // Constraint: w_2' * 2^56 + w_1' * 2^42 + w_3 * 2^28 + w_2 * 2^14 + w_1 - w_4 = 0
131 // Horner form: ((((w_2' * 2^14 + w_1') * 2^14 + w_3) * 2^14 + w_2) * 2^14 + w_1) - w_4 = 0
132 auto limb_accumulator_1_m = w_2_shift_m * SUBLIMB_SHIFT;
133 limb_accumulator_1_m += w_1_shift_m;
134 limb_accumulator_1_m *= SUBLIMB_SHIFT;
135 limb_accumulator_1_m += w_3_m;
136 limb_accumulator_1_m *= SUBLIMB_SHIFT;
137 limb_accumulator_1_m += w_2_m;
138 limb_accumulator_1_m *= SUBLIMB_SHIFT;
139 limb_accumulator_1_m += w_1_m;
140 limb_accumulator_1_m -= w_4_m;
141 auto limb_accumulator_1_m_full = limb_accumulator_1_m * q_4_m;
142
143 // Limb Accumulation Gate 2 (selected by q_3 * q_m):
144 // Reconstructs a second 68-bit limb from five 14-bit sublimbs.
145 // Constraint: w_3' * 2^56 + w_2' * 2^42 + w_1' * 2^28 + w_4 * 2^14 + w_3 - w_4' = 0
146 // Horner form: ((((w_3' * 2^14 + w_2') * 2^14 + w_1') * 2^14 + w_4) * 2^14 + w_3) - w_4' = 0
147 auto limb_accumulator_2_m = w_3_shift_m * SUBLIMB_SHIFT;
148 limb_accumulator_2_m += w_2_shift_m;
149 limb_accumulator_2_m *= SUBLIMB_SHIFT;
150 limb_accumulator_2_m += w_1_shift_m;
151 limb_accumulator_2_m *= SUBLIMB_SHIFT;
152 limb_accumulator_2_m += w_4_m;
153 limb_accumulator_2_m *= SUBLIMB_SHIFT;
154 limb_accumulator_2_m += w_3_m;
155 limb_accumulator_2_m -= w_4_shift_m;
156 auto limb_accumulator_2_m_full = limb_accumulator_2_m * q_m_m;
157
158 auto limb_accumulator_identity_m = limb_accumulator_1_m_full + limb_accumulator_2_m_full;
159 Accumulator limb_accumulator_identity(limb_accumulator_identity_m);
160 limb_accumulator_identity *= q_3_m; // deg 3
161
162 auto q_nnf_by_scaling_m = q_nnf_m * scaling_factor; // deg 1
163 auto q_nnf_by_scaling = Accumulator(q_nnf_by_scaling_m);
164
165 auto nnf_identity = non_native_field_identity + limb_accumulator_identity;
166 nnf_identity *= q_nnf_by_scaling; // deg
167 std::get<0>(accumulators) += nnf_identity; // deg
168 };
169};
170
172} // 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