Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
wnaf.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Planned, auditors: [], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
9#include <cstdint>
10
11// NOLINTBEGIN(readability-implicit-bool-conversion)
12
37namespace bb::wnaf {
38constexpr size_t SCALAR_BITS = 127;
39
40#define WNAF_SIZE(x) ((bb::wnaf::SCALAR_BITS + (x) - 1) / (x)) // NOLINT(cppcoreguidelines-macro-usage)
41
58template <size_t bits, size_t bit_position> inline uint64_t get_wnaf_bits_const(const uint64_t* scalar) noexcept
59{
60 if constexpr (bits == 0) {
61 return 0ULL;
62 } else {
63 constexpr size_t lo_limb_idx = bit_position / 64;
64 constexpr size_t hi_limb_idx = (bit_position + bits - 1) / 64;
65 constexpr uint64_t lo_shift = bit_position & 63UL;
66 constexpr uint64_t bit_mask = (1UL << static_cast<uint64_t>(bits)) - 1UL;
67
68 uint64_t lo = (scalar[lo_limb_idx] >> lo_shift);
69 if constexpr (lo_limb_idx == hi_limb_idx) {
70 return lo & bit_mask;
71 } else {
72 constexpr uint64_t hi_shift = 64UL - (bit_position & 63UL);
73 uint64_t hi = ((scalar[hi_limb_idx] << (hi_shift)));
74 return (lo | hi) & bit_mask;
75 }
76 }
77}
78
87inline uint64_t get_wnaf_bits(const uint64_t* scalar, const uint64_t bits, const uint64_t bit_position) noexcept
88{
89 const auto lo_limb_idx = static_cast<size_t>(bit_position >> 6);
90 const auto hi_limb_idx = static_cast<size_t>((bit_position + bits - 1) >> 6);
91 const uint64_t lo_shift = bit_position & 63UL;
92 const uint64_t bit_mask = (1UL << static_cast<uint64_t>(bits)) - 1UL;
93 const bool spans_limbs = (lo_limb_idx != hi_limb_idx);
94
95 const uint64_t lo = scalar[lo_limb_idx] >> lo_shift;
96 // spans_limbs is true only when bit_position is not aligned to a limb boundary, so lo_shift > 0
97 // and 64 - lo_shift ∈ [1, 63]. (If lo_shift were 0, 64 - lo_shift = 64 would be UB on uint64_t.)
98 const uint64_t hi = spans_limbs ? (scalar[hi_limb_idx] << (64UL - lo_shift)) : 0UL;
99
100 return (lo | hi) & bit_mask;
101}
102
112template <size_t num_points, size_t wnaf_bits, size_t round_i>
113inline void wnaf_round(uint64_t* scalar, uint64_t* wnaf, const uint64_t point_index, const uint64_t previous) noexcept
114{
115 constexpr size_t wnaf_entries = (SCALAR_BITS + wnaf_bits - 1) / wnaf_bits;
116 constexpr auto log2_num_points = static_cast<size_t>(numeric::get_msb(static_cast<uint32_t>(num_points)));
117
118 if constexpr (round_i < wnaf_entries - 1) {
119 uint64_t slice = get_wnaf_bits(scalar, wnaf_bits, round_i * wnaf_bits);
120 uint64_t predicate = ((slice & 1UL) == 0UL);
121 wnaf[(wnaf_entries - round_i) << log2_num_points] =
122 ((((previous - (predicate << wnaf_bits)) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
123 (point_index << 32UL);
124 wnaf_round<num_points, wnaf_bits, round_i + 1>(scalar, wnaf, point_index, slice + predicate);
125 } else {
126 constexpr size_t final_bits = SCALAR_BITS - (SCALAR_BITS / wnaf_bits) * wnaf_bits;
127 uint64_t slice = get_wnaf_bits(scalar, final_bits, (wnaf_entries - 1) * wnaf_bits);
128 uint64_t predicate = ((slice & 1UL) == 0UL);
129 wnaf[num_points] =
130 ((((previous - (predicate << wnaf_bits)) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
131 (point_index << 32UL);
132 wnaf[0] = ((slice + predicate) >> 1UL) | (point_index << 32UL);
133 }
134}
135
145template <size_t scalar_bits, size_t num_points, size_t wnaf_bits, size_t round_i>
146inline void wnaf_round(uint64_t* scalar, uint64_t* wnaf, const uint64_t point_index, const uint64_t previous) noexcept
147{
148 constexpr size_t wnaf_entries = (scalar_bits + wnaf_bits - 1) / wnaf_bits;
149 constexpr auto log2_num_points = static_cast<uint64_t>(numeric::get_msb(static_cast<uint32_t>(num_points)));
150
151 if constexpr (round_i < wnaf_entries - 1) {
152 uint64_t slice = get_wnaf_bits_const<wnaf_bits, round_i * wnaf_bits>(scalar);
153 uint64_t predicate = ((slice & 1UL) == 0UL);
154 wnaf[(wnaf_entries - round_i) << log2_num_points] =
155 ((((previous - (predicate << wnaf_bits)) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
156 (point_index << 32UL);
157 wnaf_round<scalar_bits, num_points, wnaf_bits, round_i + 1>(scalar, wnaf, point_index, slice + predicate);
158 } else {
159 constexpr size_t final_bits = ((scalar_bits / wnaf_bits) * wnaf_bits == scalar_bits)
160 ? wnaf_bits
161 : scalar_bits - (scalar_bits / wnaf_bits) * wnaf_bits;
162 uint64_t slice = get_wnaf_bits_const<final_bits, (wnaf_entries - 1) * wnaf_bits>(scalar);
163 uint64_t predicate = ((slice & 1UL) == 0UL);
164 wnaf[num_points] =
165 ((((previous - (predicate << wnaf_bits)) ^ (0UL - predicate)) >> 1UL) | (predicate << 31UL)) |
166 (point_index << 32UL);
167 wnaf[0] = ((slice + predicate) >> 1UL) | (point_index << 32UL);
168 }
169}
170
171template <size_t num_points, size_t wnaf_bits>
172inline void fixed_wnaf(uint64_t* scalar, uint64_t* wnaf, bool& skew_map, const size_t point_index) noexcept
173{
174 skew_map = ((scalar[0] & 1) == 0);
175 uint64_t previous = get_wnaf_bits_const<wnaf_bits, 0>(scalar) + static_cast<uint64_t>(skew_map);
176 wnaf_round<num_points, wnaf_bits, 1UL>(scalar, wnaf, point_index, previous);
177}
178
179template <size_t num_bits, size_t num_points, size_t wnaf_bits>
180inline void fixed_wnaf(uint64_t* scalar, uint64_t* wnaf, bool& skew_map, const size_t point_index) noexcept
181{
182 skew_map = ((scalar[0] & 1) == 0);
183 uint64_t previous = get_wnaf_bits_const<wnaf_bits, 0>(scalar) + static_cast<uint64_t>(skew_map);
184 wnaf_round<num_bits, num_points, wnaf_bits, 1UL>(scalar, wnaf, point_index, previous);
185}
186
187} // namespace bb::wnaf
188
189// NOLINTEND(readability-implicit-bool-conversion)
constexpr T get_msb(const T in)
Definition get_msb.hpp:50
Fixed-window non-adjacent form (WNAF) scalar decomposition for elliptic curve scalar multiplication.
Definition wnaf.hpp:37
constexpr size_t SCALAR_BITS
Definition wnaf.hpp:38
uint64_t get_wnaf_bits_const(const uint64_t *scalar) noexcept
Extract a window of bits consecutive bits starting at bit_position from a 128-bit scalar.
Definition wnaf.hpp:58
void wnaf_round(uint64_t *scalar, uint64_t *wnaf, const uint64_t point_index, const uint64_t previous) noexcept
Recursive WNAF round for a fixed 127-bit scalar (SCALAR_BITS).
Definition wnaf.hpp:113
uint64_t get_wnaf_bits(const uint64_t *scalar, const uint64_t bits, const uint64_t bit_position) noexcept
A variant of the previous function that the bit position and number of bits are provided at runtime.
Definition wnaf.hpp:87
void fixed_wnaf(uint64_t *scalar, uint64_t *wnaf, bool &skew_map, const size_t point_index) noexcept
Definition wnaf.hpp:172
C slice(C const &container, size_t start)
Definition container.hpp:9