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"
7#include "keccak.hpp"
8#include <gtest/gtest.h>
9
10using namespace bb;
11
12template <class Builder> class StdlibKeccak : public ::testing::Test {};
13
14using BuilderTypes = ::testing::Types<bb::UltraCircuitBuilder, bb::MegaCircuitBuilder>;
16
17namespace {
19}
20
21TYPED_TEST(StdlibKeccak, keccak_format_input_table)
22{
23 using Builder = TypeParam;
26
28
29 for (size_t i = 0; i < 25; ++i) {
30 uint64_t limb_native = engine.get_random_uint64();
31 field_ct limb(witness_ct(&builder, limb_native));
32
34
35 field_ct sparse_limb = accumulators[plookup::ColumnIdx::C2][0];
36 field_ct msb = accumulators[plookup::ColumnIdx::C3][accumulators[plookup::ColumnIdx::C3].size() - 1];
37
38 uint256_t expected_sparse = stdlib::keccak<Builder>::convert_to_sparse(limb_native);
39 uint64_t expected_msb = (limb_native >> 63) & 1ULL;
40
41 EXPECT_EQ(static_cast<uint256_t>(sparse_limb.get_value()), expected_sparse);
42 EXPECT_EQ(static_cast<uint64_t>(msb.get_value()), expected_msb);
43 }
44
45 bool proof_result = CircuitChecker::check(builder);
46 EXPECT_EQ(proof_result, true);
47}
48
49TYPED_TEST(StdlibKeccak, keccak_format_output_table)
50{
51 using Builder = TypeParam;
54
56
57 for (size_t i = 0; i < 25; ++i) {
58 uint64_t limb_native = engine.get_random_uint64();
59 uint256_t extended_native = stdlib::keccak<Builder>::convert_to_sparse(limb_native);
60 field_ct limb(witness_ct(&builder, extended_native));
61
63 field_ct normalized_limb = accumulators[plookup::ColumnIdx::C2][0];
64 EXPECT_EQ(static_cast<uint256_t>(normalized_limb.get_value()), limb_native);
65 }
66 bool proof_result = CircuitChecker::check(builder);
67 EXPECT_EQ(proof_result, true);
68}
69
70TYPED_TEST(StdlibKeccak, keccak_theta_output_table)
71{
72 using Builder = TypeParam;
75
77
78 for (size_t i = 0; i < 25; ++i) {
79 uint256_t extended_native = 0;
80 uint256_t expected_normalized = 0;
81 for (size_t j = 0; j < 8; ++j) {
82 extended_native *= 11;
83 expected_normalized *= 11;
84 uint64_t base_value = (engine.get_random_uint64() % 11);
85 uint64_t bit = base_value & 1;
86 extended_native += base_value;
87 expected_normalized += bit;
88 }
89
90 field_ct limb(witness_ct(&builder, extended_native));
92
93 EXPECT_EQ(static_cast<uint256_t>(normalized.get_value()), expected_normalized);
94 }
95
96 bool proof_result = CircuitChecker::check(builder);
97 EXPECT_EQ(proof_result, true);
98}
99
100TYPED_TEST(StdlibKeccak, keccak_rho_output_table)
101{
102 using Builder = TypeParam;
105
107
108 constexpr_for<0, 25, 1>([&]<size_t i> {
109 uint256_t extended_native = 0;
110 uint256_t binary_native = 0;
111 for (size_t j = 0; j < 64; ++j) {
112 extended_native *= 11;
113 binary_native = binary_native << 1;
114 uint64_t base_value = (engine.get_random_uint64() % 3);
115 extended_native += base_value;
116 binary_native += (base_value & 1);
117 }
118 const size_t left_bits = stdlib::keccak<Builder>::ROTATIONS[i];
119 const size_t right_bits = 64 - left_bits;
120 const uint256_t left = binary_native >> right_bits;
121 const uint256_t right = binary_native - (left << right_bits);
122 const uint256_t binary_rotated = left + (right << left_bits);
123
124 const uint256_t expected_limb = stdlib::keccak<Builder>::convert_to_sparse(binary_rotated);
125 // msb is the MSB of the normalized limb without rotation
126 const uint256_t expected_msb = (binary_native >> 63);
127 field_ct limb(witness_ct(&builder, extended_native));
128 field_ct result_msb;
129 field_ct result_limb = stdlib::keccak<Builder>::template normalize_and_rotate<i>(limb, result_msb);
130 EXPECT_EQ(static_cast<uint256_t>(result_limb.get_value()), expected_limb);
131 EXPECT_EQ(static_cast<uint256_t>(result_msb.get_value()), expected_msb);
132 });
133
134 info("num gates = ", builder.get_num_finalized_gates_inefficient());
135 bool proof_result = CircuitChecker::check(builder);
136 EXPECT_EQ(proof_result, true);
137}
138
139TYPED_TEST(StdlibKeccak, keccak_chi_output_table)
140{
141 using Builder = TypeParam;
144
145 static constexpr uint64_t chi_normalization_table[5]{
146 0, // 1 + 2a - b + c => a xor (~b & c)
147 0, 1, 1, 0,
148 };
150
151 for (size_t i = 0; i < 25; ++i) {
152 uint256_t normalized_native = 0;
153 uint256_t extended_native = 0;
154 uint256_t binary_native = 0;
155 for (size_t j = 0; j < 8; ++j) {
156 extended_native *= 11;
157 normalized_native *= 11;
158 binary_native = binary_native << 1;
159 uint64_t base_value = (engine.get_random_uint64() % 5);
160 extended_native += base_value;
161 normalized_native += chi_normalization_table[base_value];
162 binary_native += chi_normalization_table[base_value];
163 }
164 field_ct limb(witness_ct(&builder, extended_native));
165 const auto accumulators =
167
168 field_ct normalized = accumulators[plookup::ColumnIdx::C2][0];
169 field_ct msb = accumulators[plookup::ColumnIdx::C3][accumulators[plookup::ColumnIdx::C3].size() - 1];
170
171 EXPECT_EQ(static_cast<uint256_t>(normalized.get_value()), normalized_native);
172 EXPECT_EQ(static_cast<uint256_t>(msb.get_value()), binary_native >> 63);
173 }
174 info("num gates = n", builder.get_num_finalized_gates_inefficient());
175 bool proof_result = CircuitChecker::check(builder);
176 EXPECT_EQ(proof_result, true);
177}
178
179// Matches the fuzzer logic
180TYPED_TEST(StdlibKeccak, permutation_opcode)
181{
182 using Builder = TypeParam;
185
187
188 // Create a random state (25 lanes of 64 bits)
189 std::array<uint64_t, 25> native_state;
190 for (size_t i = 0; i < 25; ++i) {
191 native_state[i] = engine.get_random_uint64();
192 }
193
194 // Run native permutation
195 std::array<uint64_t, 25> expected_state = native_state;
196 ethash_keccakf1600(expected_state.data());
197
198 // Convert state to circuit field elements
199 std::array<field_ct, 25> circuit_state;
200 for (size_t i = 0; i < 25; i++) {
201 circuit_state[i] = witness_ct(&builder, native_state[i]);
202 }
203
204 // Run circuit permutation
205 auto circuit_output = stdlib::keccak<Builder>::permutation_opcode(circuit_state, &builder);
206
207 // Verify circuit correctness
208 bool proof_result = CircuitChecker::check(builder);
209 EXPECT_EQ(proof_result, true);
210
211 // Compare outputs
212 for (size_t i = 0; i < 25; i++) {
213 uint64_t circuit_value = static_cast<uint64_t>(circuit_output[i].get_value());
214 EXPECT_EQ(circuit_value, expected_state[i]);
215 }
216
217 info("num gates = ", builder.get_num_finalized_gates_inefficient());
218}
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
virtual uint64_t get_random_uint64()=0
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
Definition field.cpp:838
static std::array< field_ct, NUM_KECCAK_LANES > permutation_opcode(std::array< field_ct, NUM_KECCAK_LANES > state, Builder *context)
Definition keccak.cpp:474
static constexpr uint256_t convert_to_sparse(uint256_t input)
Convert a binary integer into a base11 integer.
Definition keccak.hpp:65
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:93
#define info(...)
Definition log.hpp:93
AluTraceBuilder builder
Definition alu.test.cpp:124
void ethash_keccakf1600(uint64_t state[KECCAKF1600_LANES]) NOEXCEPT
ECCVMCircuitBuilder Builder
numeric::RNG & engine
stdlib::witness_t< Builder > witness_ct
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
Definition engine.cpp:245
@ KECCAK_FORMAT_INPUT
Definition types.hpp:131
@ KECCAK_FORMAT_OUTPUT
Definition types.hpp:132
@ KECCAK_CHI_OUTPUT
Definition types.hpp:130
@ KECCAK_THETA_OUTPUT
Definition types.hpp:129
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
TYPED_TEST_SUITE(CommitmentKeyTest, Curves)
TYPED_TEST(CommitmentKeyTest, CommitToZeroPoly)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
::testing::Types< UltraCircuitBuilder, MegaCircuitBuilder > BuilderTypes