Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
biggroup_edgecase_handling.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Suyash], commit: 553c5eb82901955c638b943065acd3e47fc918c0}
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
13
15
25template <typename C, class Fq, class Fr, class G>
27{
28 constexpr typename G::affine_element offset_generator =
29 get_precomputed_generators<G, "biggroup table offset generator", 1>()[0];
30
31 return offset_generator;
32}
33
47template <typename C, class Fq, class Fr, class G>
49 mask_points(const std::vector<element>& _points, const std::vector<Fr>& _scalars)
50{
52 std::vector<Fr> scalars;
53 BB_ASSERT_EQ(_points.size(), _scalars.size());
54
55 // Sample a random curve point as the offset generator (free witness).
56 // The prover provides this point: the circuit only constrains it to lie on the curve.
57 C* builder = validate_context<C>(validate_context<C>(_points), validate_context<C>(_scalars));
58 const typename G::affine_element native_offset_generator = typename G::affine_element(G::element::random_element());
59 const element offset_generator_element = element::from_witness(builder, native_offset_generator);
60
61 // Disallow offset generator G = ∞ (point at infinity) because the downstream ROM table logic relies on
62 // none of the points being at infinity. If we allow any point to be at infinity in ROM table construction,
63 // a malicious prover can cause the output of the MSM to be wrong.
64 offset_generator_element.is_point_at_infinity().assert_equal(
65 false, "mask_points: offset generator must not be the point at infinity");
66
67 auto empty_tag = OriginTag::constant(); // Disable origin checking during intermediate operations
68 offset_generator_element.set_origin_tag(empty_tag);
69
70 element running_point = offset_generator_element;
71
72 // Start the running scalar at 1
73 Fr running_scalar = Fr(1);
74 Fr last_scalar = Fr(0);
75
76 // For each point and scalar
77 for (size_t i = 0; i < _points.size(); i++) {
78 scalars.push_back(_scalars[i]);
79
80 // Convert point into point + (2ⁱ)⋅G_offset
81 element masked = _points[i].add_internal(running_point);
82 // Each masked point must also be finite, for the same ROM table reason as the offset generator above.
84 "mask_points: masked point must not be the point at infinity");
85 points.push_back(masked);
86
87 // Add 2ⁱ⋅scalar_i to the last scalar
88 last_scalar += _scalars[i] * running_scalar;
89
90 // Double the running scalar and point for next iteration
91 running_scalar += running_scalar;
92 running_point = running_point.dbl_internal();
93 }
94
95 // Add a scalar -(<(1, 2, 2²,...,2ⁿ⁻¹),(scalar₀,...,scalarₙ₋₁)> / 2ⁿ)
96 const uint32_t n = static_cast<uint32_t>(_points.size());
97 const Fr two_power_n = Fr(2).pow(n);
98 const Fr two_power_n_inverse = two_power_n.invert();
99 last_scalar *= two_power_n_inverse;
100 scalars.push_back(-last_scalar);
101 if constexpr (Fr::is_composite) {
102 scalars.back().self_reduce();
103 }
104 // Add in-circuit 2ⁿ·G_offset to points
105 points.push_back(running_point);
106
107 return { points, scalars, offset_generator_element };
108}
109
114template <typename C, class Fq, class Fr, class G>
116 const std::vector<element>& _points, const std::vector<Fr>& _scalars)
117{
118 C* builder = validate_context<C>(validate_context<C>(_points), validate_context<C>(_scalars));
120 std::vector<Fr> scalars;
121 element one = element::one(builder);
122
123 for (auto [_point, _scalar] : zip_view(_points, _scalars)) {
124 bool_ct is_point_at_infinity = _point.is_point_at_infinity();
125 if (is_point_at_infinity.get_value() && static_cast<bool>(is_point_at_infinity.is_constant())) {
126 // if point is at infinity and a circuit constant we can just skip.
127 continue;
128 }
129 if (_scalar.get_value() == 0 && _scalar.is_constant()) {
130 // if scalar multiplier is 0 and also a constant, we can skip
131 continue;
132 }
133
134 // Select either the point at infinity or the fixed generator
135 element point = _point.conditional_select(one, is_point_at_infinity);
136
137 Fr scalar;
138 if constexpr (!Fr::is_composite) {
139 // For field_t (non-composite), use internal version to avoid premature normalization
140 scalar = Fr::conditional_assign_internal(is_point_at_infinity, 0, _scalar);
141 } else {
142 // For bigfield (composite), conditional_assign doesn't normalize anyway
143 scalar = Fr::conditional_assign(is_point_at_infinity, 0, _scalar);
144 }
145
146 // Push the selected point and scalar to their respective vectors
147 points.push_back(point);
148 scalars.push_back(scalar);
149 }
150
151 return { points, scalars };
152}
153} // namespace bb::stdlib::element_default
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:83
Implements boolean logic in-circuit.
Definition bool.hpp:60
bool get_value() const
Definition bool.hpp:125
bool is_constant() const
Definition bool.hpp:127
void assert_equal(const bool_t &rhs, std::string const &msg="bool_t::assert_equal") const
Implements copy constraint for bool_t elements.
Definition bool.cpp:433
element add_internal(const element &other) const
Internal implementation of ECC point addition.
void set_origin_tag(OriginTag tag) const
Definition biggroup.hpp:430
element dbl_internal() const
Internal implementation of point doubling.
element conditional_select(const element &other, const bool_ct &predicate) const
Selects this if predicate is false, other if predicate is true.
Definition biggroup.hpp:237
AluTraceBuilder builder
Definition alu.test.cpp:124
#define G(r, i, a, b, c, d)
Definition blake2s.cpp:116
constexpr std::span< const typename Group::affine_element > get_precomputed_generators()
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Curve::ScalarField Fr
static OriginTag constant()
BB_INLINE constexpr field pow(const uint256_t &exponent) const noexcept
constexpr field invert() const noexcept