Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
address_derivation.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
25
26namespace bb::avm2::constraining {
27namespace {
28
29using ::testing::Return;
30using ::testing::StrictMock;
31
32using tracegen::AddressDerivationTraceBuilder;
33using tracegen::EccTraceBuilder;
34using tracegen::Poseidon2TraceBuilder;
35using tracegen::TestTraceContainer;
36
37using simulation::AddressDerivation;
38using simulation::AddressDerivationEvent;
40using simulation::Ecc;
41using simulation::EccAddEvent;
42using simulation::EccAddMemoryEvent;
43using simulation::EventEmitter;
45using simulation::MockExecutionIdManager;
46using simulation::MockGreaterThan;
47using simulation::NoopEventEmitter;
48using simulation::Poseidon2;
49using simulation::Poseidon2HashEvent;
50using simulation::Poseidon2PermutationEvent;
51using simulation::Poseidon2PermutationMemoryEvent;
52using simulation::PureToRadix;
53using simulation::ScalarMulEvent;
54
56using C = Column;
57using address_derivation_relation = bb::avm2::address_derivation<FF>;
58using poseidon2_relation = bb::avm2::poseidon2_hash<FF>;
59using ecadd_relation = bb::avm2::ecc<FF>;
60using scalar_mul_relation = bb::avm2::scalar_mul<FF>;
62
63TEST(AddressDerivationConstrainingTest, EmptyRow)
64{
65 check_relation<address_derivation_relation>(testing::empty_trace());
66}
67
68TEST(AddressDerivationConstrainingTest, Basic)
69{
70 TestTraceContainer trace;
71 AddressDerivationTraceBuilder builder;
72
74
75 FF salted_initialization_hash = poseidon2::hash({ DOM_SEP__SALTED_INITIALIZATION_HASH,
76 instance.salt,
77 instance.initialization_hash,
78 instance.deployer,
79 instance.immutables_hash });
80
81 FF partial_address =
82 poseidon2::hash({ DOM_SEP__PARTIAL_ADDRESS, instance.original_contract_class_id, salted_initialization_hash });
83
84 FF public_keys_hash = hash_public_keys(instance.public_keys);
85 FF preaddress = poseidon2::hash({ DOM_SEP__CONTRACT_ADDRESS_V2, public_keys_hash, partial_address });
86
88 EmbeddedCurvePoint preaddress_public_key = g1 * Fq(preaddress);
89 EmbeddedCurvePoint address_point = preaddress_public_key + instance.public_keys.incoming_viewing_key;
90
91 builder.process({ { .address = address_point.x(),
93 .salted_initialization_hash = salted_initialization_hash,
94 .partial_address = partial_address,
95 .public_keys_hash = public_keys_hash,
96 .preaddress = preaddress,
97 .preaddress_public_key = preaddress_public_key,
98 .address_point = address_point } },
99 trace);
100
101 EXPECT_EQ(trace.get_num_rows(), 1);
102 check_relation<address_derivation_relation>(trace);
103}
104
105TEST(AddressDerivationConstrainingTest, WithInteractions)
106{
107 EventEmitter<EccAddEvent> ecadd_event_emitter;
108 EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
109 NoopEventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;
110 EventEmitter<Poseidon2HashEvent> hash_event_emitter;
111 NoopEventEmitter<Poseidon2PermutationEvent> perm_event_emitter;
112 NoopEventEmitter<Poseidon2PermutationMemoryEvent> perm_mem_event_emitter;
113 EventEmitter<AddressDerivationEvent> address_derivation_event_emitter;
114
115 StrictMock<MockExecutionIdManager> mock_exec_id_manager;
116 EXPECT_CALL(mock_exec_id_manager, get_execution_id)
117 .WillRepeatedly(Return(0)); // Use a fixed execution ID for the test
118 StrictMock<MockGreaterThan> mock_gt;
119 Poseidon2 poseidon2_simulator(
121
122 PureToRadix to_radix_simulator;
123 Ecc ecc_simulator(mock_exec_id_manager,
124 mock_gt,
125 to_radix_simulator,
126 ecadd_event_emitter,
127 scalar_mul_event_emitter,
128 ecc_add_memory_event_emitter);
129
130 AddressDerivation address_derivation(poseidon2_simulator, ecc_simulator, address_derivation_event_emitter);
131
132 TestTraceContainer trace({
133 { { C::precomputed_first_row, 1 } },
134 });
135
136 AddressDerivationTraceBuilder builder;
137 Poseidon2TraceBuilder poseidon2_builder;
138 EccTraceBuilder ecc_builder;
139
140 ContractInstance instance = testing::random_contract_instance();
142 address_derivation.assert_derivation(address, instance);
143
144 builder.process(address_derivation_event_emitter.dump_events(), trace);
146 ecc_builder.process_add(ecadd_event_emitter.dump_events(), trace);
147 ecc_builder.process_scalar_mul(scalar_mul_event_emitter.dump_events(), trace);
148
149 check_all_interactions<AddressDerivationTraceBuilder>(trace);
150 check_relation<address_derivation_relation>(trace);
151}
152
153TEST(AddressDerivationConstrainingTest, NegativeWithInteractions)
154{
155 EventEmitter<EccAddEvent> ecadd_event_emitter;
156 EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
157 NoopEventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;
158 EventEmitter<Poseidon2HashEvent> hash_event_emitter;
159 NoopEventEmitter<Poseidon2PermutationEvent> perm_event_emitter;
160 NoopEventEmitter<Poseidon2PermutationMemoryEvent> perm_mem_event_emitter;
161 EventEmitter<AddressDerivationEvent> address_derivation_event_emitter;
162
163 StrictMock<MockExecutionIdManager> mock_exec_id_manager;
164 EXPECT_CALL(mock_exec_id_manager, get_execution_id)
165 .WillRepeatedly(Return(0)); // Use a fixed execution ID for the test
166 StrictMock<MockGreaterThan> mock_gt;
167 Poseidon2 poseidon2_simulator(
169
170 PureToRadix to_radix_simulator;
171 Ecc ecc_simulator(mock_exec_id_manager,
172 mock_gt,
173 to_radix_simulator,
174 ecadd_event_emitter,
175 scalar_mul_event_emitter,
176 ecc_add_memory_event_emitter);
177
178 AddressDerivation address_derivation(poseidon2_simulator, ecc_simulator, address_derivation_event_emitter);
179
180 TestTraceContainer trace({
181 { { C::precomputed_first_row, 1 } },
182 });
183
184 AddressDerivationTraceBuilder builder;
185 Poseidon2TraceBuilder poseidon2_builder;
186 EccTraceBuilder ecc_builder;
187
188 ContractInstance instance = testing::random_contract_instance();
190 address_derivation.assert_derivation(address, instance);
191
192 builder.process(address_derivation_event_emitter.dump_events(), trace);
194 ecc_builder.process_add(ecadd_event_emitter.dump_events(), trace);
195 ecc_builder.process_scalar_mul(scalar_mul_event_emitter.dump_events(), trace);
196
197 check_all_interactions<AddressDerivationTraceBuilder>(trace);
198 check_relation<address_derivation_relation>(trace);
199
200 // Mutate the final address to the wrong value.
201 trace.set(C::address_derivation_address, 0, 1);
203 (check_interaction<AddressDerivationTraceBuilder, lookup_address_derivation_address_ecadd_settings>(trace)),
204 "Failed.*ADDRESS_ECADD. Could not find tuple in destination.");
205
206 // Reset.
207 trace.set(C::address_derivation_address, 0, address);
208 // Mutate the preaddress to the wrong value.
209 trace.set(C::address_derivation_preaddress, 0, 1);
210 // Both the derivation via hash and scalar mul of preaddress * G1 will fail.
212 (check_interaction<AddressDerivationTraceBuilder, lookup_address_derivation_preaddress_poseidon2_settings>(
213 trace)),
214 "Failed.*PREADDRESS_POSEIDON2. Could not find tuple in destination.");
216 (check_interaction<AddressDerivationTraceBuilder, lookup_address_derivation_preaddress_scalar_mul_settings>(
217 trace)),
218 "Failed.*PREADDRESS_SCALAR_MUL. Could not find tuple in destination.");
219}
220
221TEST(AddressDerivationConstrainingTest, NegativeMutateImmutablesHash)
222{
223 EventEmitter<EccAddEvent> ecadd_event_emitter;
224 EventEmitter<ScalarMulEvent> scalar_mul_event_emitter;
225 NoopEventEmitter<EccAddMemoryEvent> ecc_add_memory_event_emitter;
226 EventEmitter<Poseidon2HashEvent> hash_event_emitter;
227 NoopEventEmitter<Poseidon2PermutationEvent> perm_event_emitter;
228 NoopEventEmitter<Poseidon2PermutationMemoryEvent> perm_mem_event_emitter;
229 EventEmitter<AddressDerivationEvent> address_derivation_event_emitter;
230
231 StrictMock<MockExecutionIdManager> mock_exec_id_manager;
232 EXPECT_CALL(mock_exec_id_manager, get_execution_id).WillRepeatedly(Return(0));
233 StrictMock<MockGreaterThan> mock_gt;
234 Poseidon2 poseidon2_simulator(
236
237 PureToRadix to_radix_simulator;
238 Ecc ecc_simulator(mock_exec_id_manager,
239 mock_gt,
240 to_radix_simulator,
241 ecadd_event_emitter,
242 scalar_mul_event_emitter,
243 ecc_add_memory_event_emitter);
244
245 AddressDerivation address_derivation(poseidon2_simulator, ecc_simulator, address_derivation_event_emitter);
246
247 TestTraceContainer trace({
248 { { C::precomputed_first_row, 1 } },
249 });
250
251 AddressDerivationTraceBuilder builder;
252 Poseidon2TraceBuilder poseidon2_builder;
253 EccTraceBuilder ecc_builder;
254
255 ContractInstance instance = testing::random_contract_instance();
257 address_derivation.assert_derivation(address, instance);
258
259 builder.process(address_derivation_event_emitter.dump_events(), trace);
261 ecc_builder.process_add(ecadd_event_emitter.dump_events(), trace);
262 ecc_builder.process_scalar_mul(scalar_mul_event_emitter.dump_events(), trace);
263
264 check_all_interactions<AddressDerivationTraceBuilder>(trace);
265 check_relation<address_derivation_relation>(trace);
266
267 // Mutate immutables_hash (the second input of the second poseidon2 round). The salted-init-hash
268 // round-2 lookup into poseidon2 should now fail because (deployer, mutated_immutables_hash, 0,
269 // salted_init_hash) no longer exists in the poseidon2 trace.
270 trace.set(C::address_derivation_immutables_hash, 0, instance.immutables_hash + 1);
272 (check_interaction<AddressDerivationTraceBuilder,
274 "Failed.*SALTED_INITIALIZATION_HASH_POSEIDON2_1. Could not find tuple in destination.");
275}
276
277TEST(AddressDerivationConstrainingTest, NegativeIVKNotOnCurve)
278{
279 TestTraceContainer trace;
280 AddressDerivationTraceBuilder builder;
281
283
284 // Mutate ivk to a point not on the curve.
285 instance.public_keys.incoming_viewing_key = AffinePoint(1, 2);
286
287 FF salted_initialization_hash = poseidon2::hash(
288 { DOM_SEP__SALTED_INITIALIZATION_HASH, instance.salt, instance.initialization_hash, instance.deployer });
289
290 FF partial_address =
291 poseidon2::hash({ DOM_SEP__PARTIAL_ADDRESS, instance.original_contract_class_id, salted_initialization_hash });
292
293 FF public_keys_hash = hash_public_keys(instance.public_keys);
294 FF preaddress = poseidon2::hash({ DOM_SEP__CONTRACT_ADDRESS_V2, public_keys_hash, partial_address });
295
297 EmbeddedCurvePoint preaddress_public_key = g1 * Fq(preaddress);
298 EmbeddedCurvePoint address_point = preaddress_public_key + instance.public_keys.incoming_viewing_key;
299
300 builder.process({ { .address = address_point.x(),
302 .salted_initialization_hash = salted_initialization_hash,
303 .partial_address = partial_address,
304 .public_keys_hash = public_keys_hash,
305 .preaddress = preaddress,
306 .preaddress_public_key = preaddress_public_key,
307 .address_point = address_point } },
308 trace);
309
311 check_relation<address_derivation_relation>(trace, address_derivation_relation::SR_IVK_ON_CURVE_CHECK),
312 "IVK_ON_CURVE_CHECK");
313}
314
315} // namespace
316} // namespace bb::avm2::constraining
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:193
std::shared_ptr< Napi::ThreadSafeFunction > instance
#define DOM_SEP__SALTED_INITIALIZATION_HASH
#define DOM_SEP__CONTRACT_ADDRESS_V2
#define DOM_SEP__PARTIAL_ADDRESS
StrictMock< MockGreaterThan > mock_gt
EventEmitter< Poseidon2PermutationMemoryEvent > perm_mem_event_emitter
EventEmitter< Poseidon2PermutationEvent > perm_event_emitter
EventEmitter< Poseidon2HashEvent > hash_event_emitter
Poseidon2TraceBuilder poseidon2_builder
void process(const simulation::EventEmitterInterface< simulation::AluEvent >::Container &events, TraceContainer &trace)
Process the ALU events and populate the ALU relevant columns in the trace.
void process_hash(const simulation::EventEmitterInterface< simulation::Poseidon2HashEvent >::Container &hash_events, TraceContainer &trace)
Processes the hash events for the Poseidon2 hash function. It populates the columns for the poseidon2...
void set(Column col, uint32_t row, const FF &value)
Native Poseidon2 hash function implementation.
Definition poseidon2.hpp:22
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
group class. Represents an elliptic curve group element. Group is parametrised by Fq and Fr
Definition group.hpp:38
AluTraceBuilder builder
Definition alu.test.cpp:124
TestTraceContainer trace
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
FF hash_public_keys(const PublicKeys &public_keys)
FF compute_contract_address(const ContractInstance &contract_instance)
ContractInstance random_contract_instance()
Definition fixtures.cpp:159
TestTraceContainer empty_trace()
Definition fixtures.cpp:153
lookup_settings< lookup_address_derivation_salted_initialization_hash_poseidon2_1_settings_ > lookup_address_derivation_salted_initialization_hash_poseidon2_1_settings
StandardAffinePoint< AvmFlavorSettings::EmbeddedCurve::AffineElement > EmbeddedCurvePoint
Definition field.hpp:12
AvmFlavorSettings::G1::Fq Fq
Definition field.hpp:11
grumpkin::g1::affine_element AffinePoint