Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
keccakf1600.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
4#include <algorithm>
5#include <cstddef>
6#include <cstdint>
7
21
22namespace bb::avm2::simulation {
23namespace {
24
25class KeccakSimulationTest : public ::testing::Test {
26 protected:
27 KeccakSimulationTest()
34 {}
35
36 MemoryStore memory;
37 ExecutionIdManager execution_id_manager;
38 NoopEventEmitter<KeccakF1600Event> keccak_event_emitter;
39 NoopEventEmitter<BitwiseEvent> bitwise_event_emitter;
40 NoopEventEmitter<RangeCheckEvent> range_check_event_emitter;
41 NoopEventEmitter<GreaterThanEvent> greater_than_event_emitter;
42 NoopEventEmitter<FieldGreaterThanEvent> field_gt_event_emitter;
43 Bitwise bitwise;
44 RangeCheck range_check;
45 FieldGreaterThan field_gt;
46 GreaterThan greater_than;
47 KeccakF1600 keccak;
48};
49
50TEST_F(KeccakSimulationTest, matchesReferenceImplementation)
51{
52 uint64_t reference_input[AVM_KECCAKF1600_STATE_SIZE] = {
53 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
54 };
55
57
58 const MemoryAddress src_addr = 1979;
59 const MemoryAddress dst_addr = 3030;
60
61 for (size_t i = 0; i < AVM_KECCAKF1600_STATE_SIZE; i++) {
62 memory.set(src_addr + static_cast<MemoryAddress>(i), MemoryValue::from<uint64_t>(input[i]));
63 }
64
65 keccak.permutation(memory, dst_addr, src_addr);
66 uint64_t output[AVM_KECCAKF1600_STATE_SIZE];
67
68 // Read output.
69 for (size_t i = 0; i < AVM_KECCAKF1600_STATE_SIZE; i++) {
70 MemoryValue val = memory.get(dst_addr + static_cast<MemoryAddress>(i));
71 EXPECT_EQ(val.get_tag(), MemoryTag::U64);
72 output[i] = val.as<uint64_t>();
73 }
74
75 ethash_keccakf1600(input.data()); // Mutate input
76 EXPECT_THAT(input, testing::ElementsAreArray(output));
77}
78
79// Test Vector from: https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KeccakF-1600-IntermediateValues.txt
80TEST_F(KeccakSimulationTest, officialTestVector)
81{
83
84 for (size_t i = 0; i < AVM_KECCAKF1600_STATE_SIZE; i++) {
85 memory.set(static_cast<MemoryAddress>(i), MemoryValue::from<uint64_t>(input[i]));
86 }
87
88 keccak.permutation(memory, 0, 0);
89
91 for (size_t i = 0; i < AVM_KECCAKF1600_STATE_SIZE; i++) {
92 MemoryValue val = memory.get(static_cast<MemoryAddress>(i));
93 EXPECT_EQ(val.get_tag(), MemoryTag::U64);
94 output[i] = val.as<uint64_t>();
95 }
96
97 EXPECT_THAT(output[0], 0xF1258F7940E1DDE7);
98 EXPECT_THAT(output[1], 0x84D5CCF933C0478A);
99 EXPECT_THAT(output[2], 0xD598261EA65AA9EE);
100 EXPECT_THAT(output[3], 0xBD1547306F80494D);
101 EXPECT_THAT(output[4], 0x8B284E056253D057);
102 EXPECT_THAT(output[5], 0xFF97A42D7F8E6FD4);
103 EXPECT_THAT(output[6], 0x90FEE5A0A44647C4);
104 EXPECT_THAT(output[7], 0x8C5BDA0CD6192E76);
105 EXPECT_THAT(output[8], 0xAD30A6F71B19059C);
106 EXPECT_THAT(output[9], 0x30935AB7D08FFC64);
107 EXPECT_THAT(output[10], 0xEB5AA93F2317D635);
108 EXPECT_THAT(output[11], 0xA9A6E6260D712103);
109 EXPECT_THAT(output[12], 0x81A57C16DBCF555F);
110 EXPECT_THAT(output[13], 0x43B831CD0347C826);
111 EXPECT_THAT(output[14], 0x01F22F1A11A5569F);
112 EXPECT_THAT(output[15], 0x05E5635A21D9AE61);
113 EXPECT_THAT(output[16], 0x64BEFEF28CC970F2);
114 EXPECT_THAT(output[17], 0x613670957BC46611);
115 EXPECT_THAT(output[18], 0xB87C5A554FD00ECB);
116 EXPECT_THAT(output[19], 0x8C3EE88A1CCF32C8);
117 EXPECT_THAT(output[20], 0x940C7922AE3A2614);
118 EXPECT_THAT(output[21], 0x1841F924A2C509E4);
119 EXPECT_THAT(output[22], 0x16F53526E70465C2);
120 EXPECT_THAT(output[23], 0x75F644E97F30A13B);
121 EXPECT_THAT(output[24], 0xEAF1FF7B5CECA249);
122
123 for (size_t i = 0; i < AVM_KECCAKF1600_STATE_SIZE; i++) {
124 memory.set(static_cast<MemoryAddress>(i), MemoryValue::from<uint64_t>(output[i]));
125 }
126
127 keccak.permutation(memory, 0, 0);
128
130 for (size_t i = 0; i < AVM_KECCAKF1600_STATE_SIZE; i++) {
131 MemoryValue val = memory.get(static_cast<MemoryAddress>(i));
132 EXPECT_EQ(val.get_tag(), MemoryTag::U64);
133 output2[i] = val.as<uint64_t>();
134 }
135
136 // 3C CB 6E F9 4D 95 5C 2D in little endian
137 EXPECT_THAT(output2[0], 0x2D5C954DF96ECB3C);
138 // 6D B5 57 70 D0 2C 33 6A in little endian
139 EXPECT_THAT(output2[1], 0x6A332CD07057B56D);
140 // 6C 6B D7 70 12 8D 3D 09 in little endian
141 EXPECT_THAT(output2[2], 0x093D8D1270D76B6C);
142 // 94 D0 69 55 B2 D9 20 8A in little endian
143 EXPECT_THAT(output2[3], 0x8A20D9B25569D094);
144 // 56 F1 E7 E5 99 4F 9C 4F in little endian
145 EXPECT_THAT(output2[4], 0x4F9C4F99E5E7F156);
146 // 38 FB 65 DA A2 B9 57 F9 in little endian
147 EXPECT_THAT(output2[5], 0xF957B9A2DA65FB38);
148 // 0D AF 75 12 AE 3D 77 85 in little endian
149 EXPECT_THAT(output2[6], 0x85773DAE1275AF0D);
150 // F7 10 D8 C3 47 F2 F4 FA in little endian
151 EXPECT_THAT(output2[7], 0xFAF4F247C3D810F7);
152 // 59 87 9A F7 E6 9E 1B 1F in little endian
153 EXPECT_THAT(output2[8], 0x1F1B9EE6F79A8759);
154 // 25 B4 98 EE 0F CC FE E4 in little endian
155 EXPECT_THAT(output2[9], 0xE4FECC0FEE98B425);
156 // A1 68 CE B9 B6 61 CE 68 in little endian
157 EXPECT_THAT(output2[10], 0x68CE61B6B9CE68A1);
158 // 4F 97 8F BA C4 66 EA DE in little endian
159 EXPECT_THAT(output2[11], 0xDEEA66C4BA8F974F);
160 // F5 B1 AF 6E 83 3D C4 33 in little endian
161 EXPECT_THAT(output2[12], 0x33C43D836EAFB1F5);
162 // D9 DB 19 27 04 54 06 E0 in little endian
163 EXPECT_THAT(output2[13], 0xE00654042719DBD9);
164 // 65 12 83 09 F0 A9 F8 7C in little endian
165 EXPECT_THAT(output2[14], 0x7CF8A9F009831265);
166 // 43 47 17 BF A6 49 54 FD in little endian
167 EXPECT_THAT(output2[15], 0xFD5449A6BF174743);
168 // 40 4B 99 D8 33 AD DD 97 in little endian
169 EXPECT_THAT(output2[16], 0x97DDAD33D8994B40);
170 // 74 E7 0B 5D FC D5 EA 48 in little endian
171 EXPECT_THAT(output2[17], 0x48EAD5FC5D0BE774);
172 // 3C B0 B7 55 EE C8 B8 E3 in little endian
173 EXPECT_THAT(output2[18], 0xE3B8C8EE55B7B03C);
174 // E9 42 9E 64 6E 22 A0 91 in little endian
175 EXPECT_THAT(output2[19], 0x91A0226E649E42E9);
176 // 7B DD BA E7 29 31 0E 90 in little endian
177 EXPECT_THAT(output2[20], 0x900E3129E7BADD7B);
178 // E8 CC A3 FA C5 9E 2A 20 in little endian
179 EXPECT_THAT(output2[21], 0x202A9EC5FAA3CCE8);
180 // B6 3D 1C 4E 46 02 34 5B in little endian
181 EXPECT_THAT(output2[22], 0x5B3402464E1C3DB6);
182 // 59 10 4C A4 62 4E 9F 60 in little endian
183 EXPECT_THAT(output2[23], 0x609F4E62A44C1059);
184 // 5C BF 8F 6A D2 6C D0 20 in little endian
185 EXPECT_THAT(output2[24], 0x20D06CD26A8FBF5C);
186}
187
188// We simulate a tag error in the memory read.
189// We test that an exception of type KeccakF1600Exception is thrown with the string
190// "Read slice tag invalid - addr: 1979 tag: 6 (MemoryTag::U128)"
191TEST_F(KeccakSimulationTest, tagError)
192{
193 const MemoryAddress src_addr = 1970;
194 const MemoryAddress src_addr_wrong_tag = 1979;
195 const MemoryAddress dst_addr = 3030;
196 const MemoryTag wrong_tag = MemoryTag::U128;
197
198 // Initialize the full slice with U64 values in standard Keccak layout
199 for (size_t i = 0; i < AVM_KECCAKF1600_STATE_SIZE; i++) {
200 memory.set(src_addr + static_cast<MemoryAddress>(i),
202 }
203
204 // Override just the first value with U128 to trigger the tag error
205 memory.set(src_addr_wrong_tag, MemoryValue::from_tag_truncating(wrong_tag, 0));
206
208 keccak.permutation(memory, dst_addr, src_addr),
209 format("Read slice tag invalid - addr: ", src_addr_wrong_tag, " tag: ", static_cast<uint32_t>(wrong_tag)));
210}
211
212TEST_F(KeccakSimulationTest, srcSliceOutOfBounds)
213{
215 const MemoryAddress dst_addr = 3030;
216
217 EXPECT_THROW_WITH_MESSAGE(keccak.permutation(memory, dst_addr, src_addr), "Read slice out of range");
218}
219
220TEST_F(KeccakSimulationTest, dstSliceOutOfBounds)
221{
222 const MemoryAddress src_addr = 1970;
224
225 EXPECT_THROW_WITH_MESSAGE(keccak.permutation(memory, dst_addr, src_addr), "Write slice out of range");
226}
227
228} // namespace
229} // namespace bb::avm2::simulation
GreaterThan greater_than
FieldGreaterThan field_gt
#define AVM_KECCAKF1600_STATE_SIZE
#define AVM_HIGHEST_MEM_ADDRESS
static TaggedValue from_tag_truncating(ValueTag tag, FF value)
void permutation(MemoryInterface &memory, MemoryAddress dst_addr, MemoryAddress src_addr) override
Permutation Keccak-f[1600] consisting in AVM_KECCAKF1600_NUM_ROUNDS (24) rounds and a state of 25 64-...
void set(MemoryAddress index, MemoryValue value) override
const MemoryValue & get(MemoryAddress index) const override
std::string format(Args... args)
Definition log.hpp:22
ExecutionIdManager execution_id_manager
EventEmitter< RangeCheckEvent > range_check_event_emitter
uint32_t dst_addr
RangeCheck range_check
void ethash_keccakf1600(uint64_t state[25]) NOEXCEPT
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessage)
Definition macros.hpp:7
TaggedValue MemoryValue
uint32_t MemoryAddress
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:185
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Bitwise bitwise
NoopEventEmitter< GreaterThanEvent > greater_than_event_emitter
NoopEventEmitter< FieldGreaterThanEvent > field_gt_event_emitter
NoopEventEmitter< BitwiseEvent > bitwise_event_emitter
KeccakF1600 keccak
NoopEventEmitter< KeccakF1600Event > keccak_event_emitter
MemoryStore memory