Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
wnaf.test.cpp
Go to the documentation of this file.
1#include "wnaf.hpp"
2#include "../curves/bn254/fr.hpp"
4#include <gtest/gtest.h>
5
6using namespace bb;
7
8namespace {
10}
11
12// NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays)
13namespace {
14
15void recover_fixed_wnaf(const uint64_t* wnaf, bool skew, uint64_t& hi, uint64_t& lo, size_t wnaf_bits)
16{
17 size_t wnaf_entries = (127 + wnaf_bits - 1) / wnaf_bits;
18 uint128_t scalar = 0; // (uint128_t)(skew);
19 for (int i = 0; i < static_cast<int>(wnaf_entries); ++i) {
20 uint64_t entry_formatted = wnaf[static_cast<size_t>(i)];
21 bool negative = (entry_formatted >> 31) != 0U;
22 uint64_t entry = ((entry_formatted & 0x0fffffffU) << 1) + 1;
23 if (negative) {
24 scalar -= (static_cast<uint128_t>(entry))
25 << static_cast<uint128_t>(wnaf_bits * (wnaf_entries - 1 - static_cast<size_t>(i)));
26 } else {
27 scalar += (static_cast<uint128_t>(entry))
28 << static_cast<uint128_t>(wnaf_bits * (wnaf_entries - 1 - static_cast<size_t>(i)));
29 }
30 }
31 scalar -= static_cast<uint128_t>(skew);
32 hi = static_cast<uint64_t>(scalar >> static_cast<uint128_t>(64));
33 lo = static_cast<uint64_t>(static_cast<uint128_t>(scalar & static_cast<uint128_t>(0xffff'ffff'ffff'ffff)));
34}
35} // namespace
36
37TEST(wnaf, WnafZero)
38{
39 uint64_t buffer[2]{ 0, 0 };
40 uint64_t wnaf[WNAF_SIZE(5)] = { 0 };
41 bool skew = false;
42 wnaf::fixed_wnaf<1, 5>(buffer, wnaf, skew, 0);
43 uint64_t recovered_hi = 0;
44 uint64_t recovered_lo = 0;
45 recover_fixed_wnaf(wnaf, skew, recovered_hi, recovered_lo, 5);
46 EXPECT_EQ(recovered_lo, 0UL);
47 EXPECT_EQ(recovered_hi, 0UL);
48 EXPECT_EQ(buffer[0], recovered_lo);
49 EXPECT_EQ(buffer[1], recovered_hi);
50}
51
52TEST(wnaf, WnafTwoBitWindow)
53{
58 constexpr uint32_t window = 2;
59 constexpr uint32_t num_bits = 254;
60 constexpr uint32_t num_quads = (num_bits >> 1) + 1;
61 uint64_t wnaf[num_quads] = { 0 };
62 bool skew = false;
63 wnaf::fixed_wnaf<256, 1, window>(&input.data[0], wnaf, skew, 0);
64
89 uint256_t recovered = 0;
90 uint256_t four_power = (uint256_t(1) << num_bits);
91 for (uint64_t i : wnaf) {
92 int extracted = 2 * (static_cast<int>(i) & 1) + 1;
93 bool sign = (i >> 31) == 0;
94
95 if (sign) {
96 recovered += uint256_t(static_cast<uint64_t>(extracted)) * four_power;
97 } else {
98 recovered -= uint256_t(static_cast<uint64_t>(extracted)) * four_power;
99 }
100 four_power >>= 2;
101 }
102 recovered -= static_cast<uint64_t>(skew);
103 EXPECT_EQ(recovered, input);
104}
105
106TEST(wnaf, WnafFixed)
107{
109 buffer.data[1] &= 0x7fffffffffffffffUL;
110 uint64_t wnaf[WNAF_SIZE(5)] = { 0 };
111 bool skew = false;
112 wnaf::fixed_wnaf<1, 5>(&buffer.data[0], wnaf, skew, 0);
113 uint64_t recovered_hi = 0;
114 uint64_t recovered_lo = 0;
115 recover_fixed_wnaf(wnaf, skew, recovered_hi, recovered_lo, 5);
116 EXPECT_EQ(buffer.data[0], recovered_lo);
117 EXPECT_EQ(buffer.data[1], recovered_hi);
118}
119
120TEST(wnaf, WnafFixedSimpleLo)
121{
122 uint64_t rand_buffer[2]{ 1, 0 };
123 uint64_t wnaf[WNAF_SIZE(5)]{ 0 };
124 bool skew = false;
125 wnaf::fixed_wnaf<1, 5>(rand_buffer, wnaf, skew, 0);
126 uint64_t recovered_hi = 0;
127 uint64_t recovered_lo = 0;
128 recover_fixed_wnaf(wnaf, skew, recovered_hi, recovered_lo, 5);
129 EXPECT_EQ(rand_buffer[0], recovered_lo);
130 EXPECT_EQ(rand_buffer[1], recovered_hi);
131}
132
133TEST(wnaf, WnafFixedSimpleHi)
134{
135 uint64_t rand_buffer[2] = { 0, 1 };
136 uint64_t wnaf[WNAF_SIZE(5)] = { 0 };
137 bool skew = false;
138 wnaf::fixed_wnaf<1, 5>(rand_buffer, wnaf, skew, 0);
139 uint64_t recovered_hi = 0;
140 uint64_t recovered_lo = 0;
141 recover_fixed_wnaf(wnaf, skew, recovered_hi, recovered_lo, 5);
142 EXPECT_EQ(rand_buffer[0], recovered_lo);
143 EXPECT_EQ(rand_buffer[1], recovered_hi);
144}
145
146TEST(wnaf, WnafFixedWithEndoSplit)
147{
149 k.data[3] &= 0x0fffffffffffffffUL;
150
151 fr k1{ 0, 0, 0, 0 };
152 fr k2{ 0, 0, 0, 0 };
153
155 uint64_t wnaf[WNAF_SIZE(5)] = { 0 };
156 uint64_t endo_wnaf[WNAF_SIZE(5)] = { 0 };
157 bool skew = false;
158 bool endo_skew = false;
159 wnaf::fixed_wnaf<1, 5>(&k1.data[0], wnaf, skew, 0);
160 wnaf::fixed_wnaf<1, 5>(&k2.data[0], endo_wnaf, endo_skew, 0);
161
162 fr k1_recovered{ 0, 0, 0, 0 };
163 fr k2_recovered{ 0, 0, 0, 0 };
164
165 recover_fixed_wnaf(wnaf, skew, k1_recovered.data[1], k1_recovered.data[0], 5);
166 recover_fixed_wnaf(endo_wnaf, endo_skew, k2_recovered.data[1], k2_recovered.data[0], 5);
167
168 fr result;
169 fr lambda = fr::cube_root_of_unity();
170 result = k2_recovered * lambda;
171 result = k1_recovered - result;
172
173 EXPECT_EQ(result, k);
174}
175
176// NOLINTEND(cppcoreguidelines-avoid-c-arrays)
virtual uint256_t get_random_uint256()=0
numeric::RNG & engine
uint8_t buffer[RANDOM_BUFFER_SIZE]
Definition engine.cpp:34
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
Definition engine.cpp:190
Entry point for Barretenberg command-line interface.
TEST(MegaCircuitBuilder, CopyConstructor)
unsigned __int128 uint128_t
Definition serialize.hpp:44
static constexpr field cube_root_of_unity()
static void split_into_endomorphism_scalars(const field &k, field &k1, field &k2)
static field random_element(numeric::RNG *engine=nullptr) noexcept
#define WNAF_SIZE(x)
Definition wnaf.hpp:16