Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
biggroup_secp256k1.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
16
17template <typename C, class Fq, class Fr, class G>
18template <typename, typename>
20{
47 const auto [u1_lo_wnaf, u1_hi_wnaf] = compute_secp256k1_endo_wnaf<8, 2, 3>(u1);
48 const auto [u2_lo_wnaf, u2_hi_wnaf] = compute_secp256k1_endo_wnaf<4, 0, 1>(u2);
49
53 auto P1 = element::one(pubkey.get_context());
54 auto P2 = pubkey;
55 const auto P1_table =
56 element::eight_bit_fixed_base_table(element::eight_bit_fixed_base_table::CurveType::SECP256K1, false);
57 const auto endoP1_table =
58 element::eight_bit_fixed_base_table(element::eight_bit_fixed_base_table::CurveType::SECP256K1, true);
59 const auto [P2_table, endoP2_table] = create_endo_pair_four_bit_table_plookup(P2);
60
61 // Initialize our accumulator
62 auto accumulator = P2_table[u2_lo_wnaf.wnaf[0]];
63
83 for (size_t i = 0; i < 16; ++i) {
84 accumulator = accumulator.dbl();
85 accumulator = accumulator.dbl();
86
87 // u2_hi_wnaf.wnaf[2 * i] is a field_t element (as are the other wnafs).
88 // See `stdlib/memory/rom_table.hpp` for how indirect array accesses are implemented in Ultra
89 const auto& add_1 = endoP2_table[u2_hi_wnaf.wnaf[2 * i]];
90 const auto& add_2 = P2_table[u2_lo_wnaf.wnaf[2 * i + 1]];
91 const auto& add_3 = endoP1_table[u1_hi_wnaf.wnaf[i]];
92 const auto& add_4 = P1_table[u1_lo_wnaf.wnaf[i]];
93 const auto& add_5 = endoP2_table[u2_hi_wnaf.wnaf[2 * i + 1]];
94 const auto& add_6 = P2_table[u2_lo_wnaf.wnaf[2 * i + 2]];
95
96 accumulator = accumulator.multiple_montgomery_ladder({ element::chain_add_accumulator(add_1),
97 element::chain_add_accumulator(add_2),
98 element::chain_add_accumulator(add_3) });
99
100 accumulator = accumulator.multiple_montgomery_ladder({ element::chain_add_accumulator(add_4),
101 element::chain_add_accumulator(add_5),
102 element::chain_add_accumulator(add_6) });
103 }
104
108 const auto& add_1 = endoP1_table[u1_hi_wnaf.least_significant_wnaf_fragment];
109 const auto& add_2 = endoP2_table[u2_hi_wnaf.least_significant_wnaf_fragment];
110 const auto& add_3 = P1_table[u1_lo_wnaf.least_significant_wnaf_fragment];
111 accumulator = element::chain_add_end(
112 element::chain_add(add_3, element::chain_add(add_2, element::chain_add_start(accumulator, add_1))));
113
120 // TODO REMOVE BOOL CASTS, VALUES HAVE ALREADY BEEN RANGE CONSTRAINED
121 const auto conditional_add = [](const element& accumulator,
122 const element& base_point,
123 const field_t<C>& positive_skew,
124 const field_t<C>& negative_skew) {
125 const bool_ct positive_skew_bool(positive_skew);
126 const bool_ct negative_skew_bool(negative_skew);
127 auto to_add = base_point;
128 to_add.y = to_add.y.conditional_negate(negative_skew_bool);
129 element result = accumulator + to_add;
130
131 // when computing the wNAF we have already validated that positive_skew and negative_skew cannot both be true
132 bool_ct skew_combined = positive_skew_bool ^ negative_skew_bool;
133 result.x = accumulator.x.conditional_select(result.x, skew_combined);
134 result.y = accumulator.y.conditional_select(result.y, skew_combined);
135 return result;
136 };
137
138 accumulator = conditional_add(accumulator, P1, u1_lo_wnaf.positive_skew, u1_lo_wnaf.negative_skew);
139 accumulator = conditional_add(accumulator, endoP1_table[128], u1_hi_wnaf.positive_skew, u1_hi_wnaf.negative_skew);
140 accumulator = conditional_add(accumulator, P2, u2_lo_wnaf.positive_skew, u2_lo_wnaf.negative_skew);
141 accumulator = conditional_add(accumulator, endoP2_table[8], u2_hi_wnaf.positive_skew, u2_hi_wnaf.negative_skew);
142
143 return accumulator;
144}
145} // namespace bb::stdlib::element_default
Implements boolean logic in-circuit.
Definition bool.hpp:59