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 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 auto empty_tag = OriginTag::constant(); // Disable origin checking during intermediate operations
61 offset_generator_element.set_origin_tag(empty_tag);
62
63 element running_point = offset_generator_element;
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].add_internal(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_internal();
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: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 set_origin_tag(OriginTag tag) const
Definition biggroup.hpp:408
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