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: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
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
43template <typename C, class Fq, class Fr, class G>
45 const std::vector<element>& _points, const std::vector<Fr>& _scalars, const Fr& masking_scalar)
46{
48 std::vector<Fr> scalars;
49 BB_ASSERT_EQ(_points.size(), _scalars.size());
50
51 BB_ASSERT_LTE(uint256_t(masking_scalar.get_value()).get_msb() + 1ULL,
52 128ULL,
53 "biggroup mask_points: masking_scalar must ≤ 128 bits");
54
55 // Get the offset generator G_offset in native and in-circuit form
56 const typename G::affine_element native_offset_generator = element::compute_table_offset_generator();
57 C* builder = validate_context<C>(validate_context<C>(_points), validate_context<C>(_scalars));
58 const element offset_generator_element = element::from_witness(builder, native_offset_generator);
59 offset_generator_element.set_origin_tag(OriginTag());
60
61 // Compute initial point to be added: (δ)⋅G_offset
62 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1585): do we really need to multiply by δ here?
63 element running_point = offset_generator_element.scalar_mul(masking_scalar, 128);
64
65 // Start the running scalar at 1
66 Fr running_scalar = Fr(1);
67 Fr last_scalar = Fr(0);
68
69 // For each point and scalar
70 for (size_t i = 0; i < _points.size(); i++) {
71 scalars.push_back(_scalars[i]);
72
73 // Convert point into point + (2ⁱ)⋅(δG_offset)
74 points.push_back(_points[i] + running_point);
75
76 // Add 2ⁱ⋅scalar_i to the last scalar
77 last_scalar += _scalars[i] * running_scalar;
78
79 // Double the running scalar and point for next iteration
80 running_scalar += running_scalar;
81 running_point = running_point.dbl();
82 }
83
84 // Add a scalar -(<δ(1, 2, 2²,...,2ⁿ⁻¹),(scalar₀,...,scalarₙ₋₁)> / 2ⁿ)
85 const uint32_t n = static_cast<uint32_t>(_points.size());
86 const Fr two_power_n = Fr(2).pow(n);
87 const Fr two_power_n_inverse = two_power_n.invert();
88 last_scalar *= two_power_n_inverse;
89 scalars.push_back(-last_scalar);
90 if constexpr (Fr::is_composite) {
91 scalars.back().self_reduce();
92 }
93 // Add in-circuit 2ⁿ.(δ.G_offset) to points
94 points.push_back(running_point);
95
96 return { points, scalars };
97}
98
103template <typename C, class Fq, class Fr, class G>
105 const std::vector<element>& _points, const std::vector<Fr>& _scalars)
106{
107 C* builder = validate_context<C>(validate_context<C>(_points), validate_context<C>(_scalars));
109 std::vector<Fr> scalars;
110 element one = element::one(builder);
111
112 for (auto [_point, _scalar] : zip_view(_points, _scalars)) {
113 bool_ct is_point_at_infinity = _point.is_point_at_infinity();
114 if (is_point_at_infinity.get_value() && static_cast<bool>(is_point_at_infinity.is_constant())) {
115 // if point is at infinity and a circuit constant we can just skip.
116 continue;
117 }
118 if (_scalar.get_value() == 0 && _scalar.is_constant()) {
119 // if scalar multiplier is 0 and also a constant, we can skip
120 continue;
121 }
122
123 // Select either the point at infinity or the fixed generator
124 element point = _point.conditional_select(one, is_point_at_infinity);
125
126 Fr scalar;
127 if constexpr (!Fr::is_composite) {
128 // For field_t (non-composite), use internal version to avoid premature normalization
129 scalar = Fr::conditional_assign_internal(is_point_at_infinity, 0, _scalar);
130 } else {
131 // For bigfield (composite), conditional_assign doesn't normalize anyway
132 scalar = Fr::conditional_assign(is_point_at_infinity, 0, _scalar);
133 }
134
135 // Push the selected point and scalar to their respective vectors
136 points.push_back(point);
137 scalars.push_back(scalar);
138 }
139
140 return { points, scalars };
141}
142} // namespace bb::stdlib::element_default
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:77
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:152
constexpr uint64_t get_msb() const
Implements boolean logic in-circuit.
Definition bool.hpp:59
bool get_value() const
Definition bool.hpp:124
bool is_constant() const
Definition bool.hpp:126
void set_origin_tag(OriginTag tag) const
Definition biggroup.hpp:405
element scalar_mul(const Fr &scalar, const size_t max_num_bits=0) const
Implements scalar multiplication that supports short scalars. For multiple scalar multiplication use ...
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
BB_INLINE constexpr field pow(const uint256_t &exponent) const noexcept
constexpr field invert() const noexcept