2#include "../curves/bn254/fr.hpp"
4#include <gtest/gtest.h>
15void recover_fixed_wnaf(
const uint64_t* wnaf,
bool skew, uint64_t& hi, uint64_t& lo,
size_t wnaf_bits)
17 const size_t wnaf_entries = (127 + wnaf_bits - 1) / wnaf_bits;
18 const uint64_t max_table_index = (1UL << (wnaf_bits - 1)) - 1;
20 for (
size_t i = 0; i < wnaf_entries; ++i) {
21 uint64_t entry = wnaf[i];
22 uint64_t table_index = entry & 0x7fffffffUL;
23 bool sign = ((entry >> 31) & 1) != 0U;
24 uint64_t point_index_bits = entry >> 32;
26 EXPECT_LE(table_index, max_table_index)
27 <<
"entry " << i <<
": table_index " << table_index <<
" exceeds max " << max_table_index;
31 EXPECT_FALSE(sign) <<
"entry 0 (most significant digit) must be positive";
35 EXPECT_EQ(point_index_bits, 0UL) <<
"entry " << i <<
": unexpected non-zero point_index bits";
40 for (
size_t i = 0; i < wnaf_entries; ++i) {
41 uint64_t entry_formatted = wnaf[i];
42 bool negative = ((entry_formatted >> 31) & 1) != 0U;
43 uint64_t digit = ((entry_formatted & 0x7fffffffUL) << 1) + 1;
44 auto shift =
static_cast<uint128_t>(wnaf_bits * (wnaf_entries - 1 - i));
46 scalar -=
static_cast<uint128_t>(digit) << shift;
48 scalar +=
static_cast<uint128_t>(digit) << shift;
52 hi =
static_cast<uint64_t
>(scalar >>
static_cast<uint128_t>(64));
53 lo =
static_cast<uint64_t
>(scalar &
static_cast<uint128_t>(0xffff'ffff'ffff'ffff));
57TEST(wnaf, GetWnafBitsConstLimbBoundary)
63 const uint64_t scalar[2] = { 0xA800000000000000ULL, 0x0000000000000015ULL };
67 EXPECT_EQ((wnaf::get_wnaf_bits_const<5, 63>(scalar)), 11ULL);
71 EXPECT_EQ((wnaf::get_wnaf_bits_const<5, 64>(scalar)), 21ULL);
75 EXPECT_EQ((wnaf::get_wnaf_bits_const<5, 65>(scalar)), 10ULL);
82 auto test_power_of_two_scalar = [](uint64_t lo, uint64_t hi) {
83 uint64_t
buffer[2] = { lo, hi };
86 wnaf::fixed_wnaf<1, 5>(
buffer, wnaf_out, skew, 0);
88 uint64_t recovered_hi = 0;
89 uint64_t recovered_lo = 0;
90 recover_fixed_wnaf(wnaf_out, skew, recovered_hi, recovered_lo, 5);
91 EXPECT_EQ(lo, recovered_lo);
92 EXPECT_EQ(hi, recovered_hi);
95 test_power_of_two_scalar(2ULL, 0ULL);
96 test_power_of_two_scalar(1ULL << 32, 0ULL);
97 test_power_of_two_scalar(0ULL, 1ULL);
98 test_power_of_two_scalar(0ULL, 1ULL << 62);
103 uint64_t
buffer[2]{ 0, 0 };
106 wnaf::fixed_wnaf<1, 5>(
buffer, wnaf, skew, 0);
107 uint64_t recovered_hi = 0;
108 uint64_t recovered_lo = 0;
109 recover_fixed_wnaf(wnaf, skew, recovered_hi, recovered_lo, 5);
110 EXPECT_EQ(recovered_lo, 0UL);
111 EXPECT_EQ(recovered_hi, 0UL);
112 EXPECT_EQ(
buffer[0], recovered_lo);
113 EXPECT_EQ(
buffer[1], recovered_hi);
122 constexpr uint32_t window = 2;
123 constexpr uint32_t num_bits = 254;
124 constexpr uint32_t num_quads = (num_bits >> 1) + 1;
125 uint64_t wnaf[num_quads] = { 0 };
127 wnaf::fixed_wnaf<256, 1, window>(&input.
data[0], wnaf, skew, 0);
155 for (uint64_t i : wnaf) {
156 int extracted = 2 * (
static_cast<int>(i) & 1) + 1;
157 bool sign = (i >> 31) == 0;
160 recovered +=
uint256_t(
static_cast<uint64_t
>(extracted)) * four_power;
162 recovered -=
uint256_t(
static_cast<uint64_t
>(extracted)) * four_power;
166 recovered -=
static_cast<uint64_t
>(skew);
167 EXPECT_EQ(recovered, input);
176 wnaf::fixed_wnaf<1, 5>(&
buffer.data[0], wnaf, skew, 0);
177 uint64_t recovered_hi = 0;
178 uint64_t recovered_lo = 0;
179 recover_fixed_wnaf(wnaf, skew, recovered_hi, recovered_lo, 5);
180 EXPECT_EQ(
buffer.data[0], recovered_lo);
181 EXPECT_EQ(
buffer.data[1], recovered_hi);
186 uint64_t rand_buffer[2]{ 1, 0 };
189 wnaf::fixed_wnaf<1, 5>(rand_buffer, wnaf, skew, 0);
190 uint64_t recovered_hi = 0;
191 uint64_t recovered_lo = 0;
192 recover_fixed_wnaf(wnaf, skew, recovered_hi, recovered_lo, 5);
193 EXPECT_EQ(rand_buffer[0], recovered_lo);
194 EXPECT_EQ(rand_buffer[1], recovered_hi);
199 uint64_t rand_buffer[2] = { 0, 1 };
202 wnaf::fixed_wnaf<1, 5>(rand_buffer, wnaf, skew, 0);
203 uint64_t recovered_hi = 0;
204 uint64_t recovered_lo = 0;
205 recover_fixed_wnaf(wnaf, skew, recovered_hi, recovered_lo, 5);
206 EXPECT_EQ(rand_buffer[0], recovered_lo);
207 EXPECT_EQ(rand_buffer[1], recovered_hi);
210TEST(wnaf, WnafFixedWithEndoSplit)
213 k.
data[3] &= 0x0fffffffffffffffUL;
220 uint64_t endo_wnaf[
WNAF_SIZE(5)] = { 0 };
222 bool endo_skew =
false;
223 wnaf::fixed_wnaf<1, 5>(&k1.data[0], wnaf, skew, 0);
224 wnaf::fixed_wnaf<1, 5>(&k2.data[0], endo_wnaf, endo_skew, 0);
226 fr k1_recovered{ 0, 0, 0, 0 };
227 fr k2_recovered{ 0, 0, 0, 0 };
229 recover_fixed_wnaf(wnaf, skew, k1_recovered.data[1], k1_recovered.data[0], 5);
230 recover_fixed_wnaf(endo_wnaf, endo_skew, k2_recovered.data[1], k2_recovered.data[0], 5);
234 result = k2_recovered * lambda;
235 result = k1_recovered - result;
237 EXPECT_EQ(result, k);
virtual uint256_t get_random_uint256()=0
std::unique_ptr< uint8_t[]> buffer
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
Entry point for Barretenberg command-line interface.
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)
unsigned __int128 uint128_t
static constexpr field cube_root_of_unity()
static void split_into_endomorphism_scalars(const field &k, field &k1, field &k2)
Full-width endomorphism decomposition: k ≡ k1 - k2·λ (mod r). Modifies the field elements k1 and k2.
static field random_element(numeric::RNG *engine=nullptr) noexcept