Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
keccak.test.cpp
Go to the documentation of this file.
2#include "../../primitives/plookup/plookup.hpp"
5#include "keccak.hpp"
6#include <gtest/gtest.h>
7
8using namespace bb;
9
15
16namespace {
18}
19
20TEST(stdlib_keccak, keccak_format_input_table)
21{
23
24 for (size_t i = 0; i < 25; ++i) {
25 uint64_t limb_native = engine.get_random_uint64();
26 field_ct limb(witness_ct(&builder, limb_native));
28 }
29
30 bool proof_result = CircuitChecker::check(builder);
31 EXPECT_EQ(proof_result, true);
32}
33
34TEST(stdlib_keccak, keccak_format_output_table)
35{
37
38 for (size_t i = 0; i < 25; ++i) {
39 uint64_t limb_native = engine.get_random_uint64();
40 uint256_t extended_native = stdlib::keccak<Builder>::convert_to_sparse(limb_native);
41 field_ct limb(witness_ct(&builder, extended_native));
43 }
44 bool proof_result = CircuitChecker::check(builder);
45 EXPECT_EQ(proof_result, true);
46}
47
48TEST(stdlib_keccak, keccak_theta_output_table)
49{
51
52 for (size_t i = 0; i < 25; ++i) {
53 uint256_t extended_native = 0;
54 for (size_t j = 0; j < 8; ++j) {
55 extended_native *= 11;
56 uint64_t base_value = (engine.get_random_uint64() % 11);
57 extended_native += base_value;
58 }
59 field_ct limb(witness_ct(&builder, extended_native));
61 }
62 bool proof_result = CircuitChecker::check(builder);
63 EXPECT_EQ(proof_result, true);
64}
65
66TEST(stdlib_keccak, keccak_rho_output_table)
67{
68 // TODO(https://github.com/AztecProtocol/barretenberg/issues/662)
69 GTEST_SKIP() << "Bug in constant case?";
71
72 constexpr_for<0, 25, 1>([&]<size_t i> {
73 uint256_t extended_native = 0;
74 uint256_t binary_native = 0;
75 for (size_t j = 0; j < 64; ++j) {
76 extended_native *= 11;
77 binary_native = binary_native << 1;
78 uint64_t base_value = (engine.get_random_uint64() % 3);
79 extended_native += base_value;
80 binary_native += (base_value & 1);
81 }
82 const size_t left_bits = stdlib::keccak<Builder>::ROTATIONS[i];
83 const size_t right_bits = 64 - left_bits;
84 const uint256_t left = binary_native >> right_bits;
85 const uint256_t right = binary_native - (left << right_bits);
86 const uint256_t binary_rotated = left + (right << left_bits);
87
88 const uint256_t expected_limb = stdlib::keccak<Builder>::convert_to_sparse(binary_rotated);
89 // msb only is correct iff rotation == 0 (no need to get msb for rotated lookups)
90 const uint256_t expected_msb = (binary_native >> 63);
91 field_ct limb(witness_ct(&builder, extended_native));
92 field_ct result_msb;
93 field_ct result_limb = stdlib::keccak<Builder>::normalize_and_rotate<i>(limb, result_msb);
94 EXPECT_EQ(static_cast<uint256_t>(result_limb.get_value()), expected_limb);
95 EXPECT_EQ(static_cast<uint256_t>(result_msb.get_value()), expected_msb);
96 });
97
98 info("num gates = ", builder.get_estimated_num_finalized_gates());
99 bool proof_result = CircuitChecker::check(builder);
100 EXPECT_EQ(proof_result, true);
101}
102
103TEST(stdlib_keccak, keccak_chi_output_table)
104{
105 static constexpr uint64_t chi_normalization_table[5]{
106 0, // 1 + 2a - b + c => a xor (~b & c)
107 0, 1, 1, 0,
108 };
110
111 for (size_t i = 0; i < 25; ++i) {
112 uint256_t normalized_native = 0;
113 uint256_t extended_native = 0;
114 uint256_t binary_native = 0;
115 for (size_t j = 0; j < 8; ++j) {
116 extended_native *= 11;
117 normalized_native *= 11;
118 binary_native = binary_native << 1;
119 uint64_t base_value = (engine.get_random_uint64() % 5);
120 extended_native += base_value;
121 normalized_native += chi_normalization_table[base_value];
122 binary_native += chi_normalization_table[base_value];
123 }
124 field_ct limb(witness_ct(&builder, extended_native));
125 const auto accumulators =
127
128 field_ct normalized = accumulators[plookup::ColumnIdx::C2][0];
129 field_ct msb = accumulators[plookup::ColumnIdx::C3][accumulators[plookup::ColumnIdx::C3].size() - 1];
130
131 EXPECT_EQ(static_cast<uint256_t>(normalized.get_value()), normalized_native);
132 EXPECT_EQ(static_cast<uint256_t>(msb.get_value()), binary_native >> 63);
133 }
134 info("num gates = n", builder.get_estimated_num_finalized_gates());
135 bool proof_result = CircuitChecker::check(builder);
136 EXPECT_EQ(proof_result, true);
137}
138
139TEST(stdlib_keccak, test_format_input_lanes)
140{
141 GTEST_SKIP() << "Unneeded?";
142
144
145 for (size_t i = 543; i < 544; ++i) {
146 std::cout << "i = " << i << std::endl;
147 std::string input;
148 for (size_t j = 0; j < i; ++j) {
149 input += "a";
150 }
151
152 // std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01";
153 std::vector<uint8_t> input_v(input.begin(), input.end());
154 const size_t excess_zeroes = i % 543;
155 std::vector<uint8_t> input_padded_v(input.begin(), input.end());
156 for (size_t k = 0; k < excess_zeroes; ++k) {
157 input_padded_v.push_back(0);
158 }
159 byte_array input_arr(&builder, input_v);
160 byte_array input_padded_arr(&builder, input_padded_v);
161
164
165 EXPECT_GT(result.size(), expected.size() - 1);
166
167 for (size_t j = 0; j < expected.size(); ++j) {
168 EXPECT_EQ(result[j].get_value(), expected[j].get_value());
169 }
170 for (size_t j = expected.size(); j < result.size(); ++j) {
171 EXPECT_EQ(result[j].get_value(), 0);
172 }
173 }
174
175 bool proof_result = CircuitChecker::check(builder);
176 EXPECT_EQ(proof_result, true);
177}
178
179TEST(stdlib_keccak, test_single_block)
180{
182 std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01";
183 std::vector<uint8_t> input_v(input.begin(), input.end());
184
185 byte_array input_arr(&builder, input_v);
186 byte_array output = stdlib::keccak<Builder>::hash(input_arr);
187
188 std::vector<uint8_t> expected = stdlib::keccak<Builder>::hash_native(input_v);
189
190 EXPECT_EQ(output.get_value(), expected);
191
192 builder.print_num_estimated_finalized_gates();
193
194 bool proof_result = CircuitChecker::check(builder);
195 EXPECT_EQ(proof_result, true);
196}
197
198TEST(stdlib_keccak, test_double_block)
199{
200
201 GTEST_SKIP() << "Bug in constant case?";
202
204 std::string input = "";
205 for (size_t i = 0; i < 200; ++i) {
206 input += "a";
207 }
208 std::vector<uint8_t> input_v(input.begin(), input.end());
209
210 byte_array input_arr(&builder, input_v);
211 byte_array output = stdlib::keccak<Builder>::hash(input_arr);
212
213 std::vector<uint8_t> expected = stdlib::keccak<Builder>::hash_native(input_v);
214
215 EXPECT_EQ(output.get_value(), expected);
216
217 builder.print_num_estimated_finalized_gates();
218
219 bool proof_result = CircuitChecker::check(builder);
220 EXPECT_EQ(proof_result, true);
221}
222
223TEST(stdlib_keccak, test_permutation_opcode_single_block)
224{
226 std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01";
227 std::vector<uint8_t> input_v(input.begin(), input.end());
228
229 byte_array input_arr(&builder, input_v);
231
232 std::vector<uint8_t> expected = stdlib::keccak<Builder>::hash_native(input_v);
233
234 EXPECT_EQ(output.get_value(), expected);
235
236 builder.print_num_estimated_finalized_gates();
237
238 bool proof_result = CircuitChecker::check(builder);
239 EXPECT_EQ(proof_result, true);
240}
241
242TEST(stdlib_keccak, test_permutation_opcode_double_block)
243{
245 std::string input = "";
246 for (size_t i = 0; i < 200; ++i) {
247 input += "a";
248 }
249 std::vector<uint8_t> input_v(input.begin(), input.end());
250
251 byte_array input_arr(&builder, input_v);
253
254 std::vector<uint8_t> expected = stdlib::keccak<Builder>::hash_native(input_v);
255
256 EXPECT_EQ(output.get_value(), expected);
257
258 builder.print_num_estimated_finalized_gates();
259
260 bool proof_result = CircuitChecker::check(builder);
261 EXPECT_EQ(proof_result, true);
262}
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
virtual uint64_t get_random_uint64()=0
Represents a dynamic array of bytes in-circuit.
std::vector< uint8_t > get_value() const
A helper converting a byte_array into the vector of its uint8_t values.
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
Definition field.cpp:827
KECCAAAAAAAAAAK.
Definition keccak.hpp:25
static std::vector< field_ct > format_input_lanes(byte_array_ct &input)
Convert the input buffer into 8-bit keccak lanes in little-endian form. Additionally,...
Definition keccak.cpp:559
static std::vector< uint8_t > hash_native(const std::vector< uint8_t > &data)
Definition keccak.hpp:181
static byte_array_ct hash_using_permutation_opcode(byte_array_ct &input)
Definition keccak.cpp:680
static byte_array_ct hash(byte_array_ct &input)
Definition keccak.cpp:706
static constexpr uint256_t convert_to_sparse(uint256_t input)
Convert a binary integer into a base11 integer.
Definition keccak.hpp:76
static plookup::ReadData< field_pt > get_lookup_accumulators(const plookup::MultiTableId id, const field_pt &key_a, const field_pt &key_b=0, const bool is_2_to_1_lookup=false)
Definition plookup.cpp:19
static field_pt read_from_1_to_2_table(const plookup::MultiTableId id, const field_pt &key_a)
Definition plookup.cpp:89
void info(Args... args)
Definition log.hpp:70
AluTraceBuilder builder
Definition alu.test.cpp:123
numeric::RNG & engine
stdlib::witness_t< Builder > witness_ct
UltraCircuitBuilder Builder
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
Definition engine.cpp:190
@ KECCAK_FORMAT_INPUT
Definition types.hpp:135
@ KECCAK_FORMAT_OUTPUT
Definition types.hpp:136
@ KECCAK_CHI_OUTPUT
Definition types.hpp:134
@ KECCAK_THETA_OUTPUT
Definition types.hpp:133
Entry point for Barretenberg command-line interface.
TEST(MegaCircuitBuilder, CopyConstructor)
UltraCircuitBuilder_< UltraExecutionTraceBlocks > UltraCircuitBuilder
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13