Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
simulation_helper.cpp
Go to the documentation of this file.
2
3#include <cstdint>
4
10
25
26// Events.
50
51// Gadgets.
79
80// Standalone.
94
95namespace bb::avm2 {
96
97using namespace bb::avm2::simulation;
98
100{
101 BB_BENCH_NAME("AvmSimulationHelper::simulate_for_witgen");
102
103 EventEmitter<ExecutionEvent> execution_emitter;
106 EventEmitter<DataCopyEvent> data_copy_emitter;
107 EventEmitter<MemoryEvent> memory_emitter;
108 EventEmitter<BytecodeRetrievalEvent> bytecode_retrieval_emitter;
109 EventEmitter<BytecodeHashingEvent> bytecode_hashing_emitter;
110 EventEmitter<BytecodeDecompositionEvent> bytecode_decomposition_emitter;
111 DeduplicatingEventEmitter<InstructionFetchingEvent> instruction_fetching_emitter;
112 EventEmitter<AddressDerivationEvent> address_derivation_emitter;
113 EventEmitter<ClassIdDerivationEvent> class_id_derivation_emitter;
114 EventEmitter<SiloingEvent> siloing_emitter;
115 EventEmitter<Sha256CompressionEvent> sha256_compression_emitter;
116 EventEmitter<EccAddEvent> ecc_add_emitter;
117 EventEmitter<ScalarMulEvent> scalar_mul_emitter;
118 EventEmitter<EccAddMemoryEvent> ecc_add_memory_emitter;
119 EventEmitter<Poseidon2HashEvent> poseidon2_hash_emitter;
120 EventEmitter<Poseidon2PermutationEvent> poseidon2_perm_emitter;
121 EventEmitter<Poseidon2PermutationMemoryEvent> poseidon2_perm_mem_emitter;
122 EventEmitter<KeccakF1600Event> keccakf1600_emitter;
123 EventEmitter<ToRadixEvent> to_radix_emitter;
124 EventEmitter<ToRadixMemoryEvent> to_radix_memory_emitter;
126 EventEmitter<MerkleCheckEvent> merkle_check_emitter;
128 EventEmitter<ContextStackEvent> context_stack_emitter;
129 EventEmitter<PublicDataTreeCheckEvent> public_data_tree_check_emitter;
130 EventEmitter<UpdateCheckEvent> update_check_emitter;
131 EventEmitter<NullifierTreeCheckEvent> nullifier_tree_check_emitter;
133 EventEmitter<CalldataEvent> calldata_emitter;
134 EventEmitter<InternalCallStackEvent> internal_call_stack_emitter;
135 EventEmitter<NoteHashTreeCheckEvent> note_hash_tree_check_emitter;
136 EventEmitter<WrittenPublicDataSlotsTreeCheckEvent> written_public_data_slots_tree_check_emitter;
138 EventEmitter<ContractInstanceRetrievalEvent> contract_instance_retrieval_emitter;
139 EventEmitter<GetContractInstanceEvent> get_contract_instance_emitter;
140 EventEmitter<L1ToL2MessageTreeCheckEvent> l1_to_l2_msg_tree_check_emitter;
141 EventEmitter<EmitUnencryptedLogEvent> emit_unencrypted_log_emitter;
142 EventEmitter<RetrievedBytecodesTreeCheckEvent> retrieved_bytecodes_tree_check_emitter;
143
147 GreaterThan greater_than(field_gt, range_check, greater_than_emitter);
148 ToRadix to_radix(execution_id_manager, greater_than, to_radix_emitter, to_radix_memory_emitter);
150 execution_id_manager, greater_than, poseidon2_hash_emitter, poseidon2_perm_emitter, poseidon2_perm_mem_emitter);
151 MerkleCheck merkle_check(poseidon2, merkle_check_emitter);
152 PublicDataTreeCheck public_data_tree_check(
153 poseidon2, merkle_check, field_gt, execution_id_manager, public_data_tree_check_emitter);
156 field_gt,
158 written_public_data_slots_tree_check_emitter);
160 poseidon2, merkle_check, field_gt, build_retrieved_bytecodes_tree(), retrieved_bytecodes_tree_check_emitter);
161 NullifierTreeCheck nullifier_tree_check(poseidon2, merkle_check, field_gt, nullifier_tree_check_emitter);
162
163 // The protocol requires at least one non-revertible nullifier in the transaction (used for uniqueness of note
164 // hashes).
166 throw std::runtime_error("Non-revertible nullifiers are empty in the transaction.");
167 }
168
170 poseidon2,
172 note_hash_tree_check_emitter);
173 L1ToL2MessageTreeCheck l1_to_l2_msg_tree_check(merkle_check, l1_to_l2_msg_tree_check_emitter);
174 EmitUnencryptedLog emit_unencrypted_log_component(execution_id_manager, greater_than, emit_unencrypted_log_emitter);
176 Bitwise bitwise(bitwise_emitter);
177 Sha256 sha256(execution_id_manager, bitwise, greater_than, sha256_compression_emitter);
179
180 Ecc ecc(execution_id_manager, greater_than, to_radix, ecc_add_emitter, scalar_mul_emitter, ecc_add_memory_emitter);
181 AddressDerivation address_derivation(poseidon2, ecc, address_derivation_emitter);
182 ClassIdDerivation class_id_derivation(poseidon2, class_id_derivation_emitter);
183 HintedRawContractDB raw_contract_db(hints);
184 HintedRawMerkleDB raw_merkle_db(hints);
185
187
188 MerkleDB base_merkle_db(raw_merkle_db,
189 public_data_tree_check,
190 nullifier_tree_check,
193 l1_to_l2_msg_tree_check);
194 base_merkle_db.add_checkpoint_listener(note_hash_tree_check);
195 base_merkle_db.add_checkpoint_listener(nullifier_tree_check);
196 base_merkle_db.add_checkpoint_listener(public_data_tree_check);
197 // This one is only needed for events.
198 base_merkle_db.add_checkpoint_listener(emit_unencrypted_log_component);
199
200 // Side effect tracking is only strictly needed for logs and L2-to-L1 messages.
202
205
207 poseidon2, range_check, greater_than, merkle_db, update_check_emitter, hints.global_variables);
208
209 BytecodeHasher bytecode_hasher(poseidon2, bytecode_hashing_emitter);
210 Siloing siloing(siloing_emitter);
212
214 contract_db, merkle_db, update_check, field_gt, hints.protocol_contracts, contract_instance_retrieval_emitter);
215
216 TxBytecodeManager bytecode_manager(contract_db,
217 merkle_db,
222 bytecode_retrieval_emitter,
223 bytecode_decomposition_emitter,
224 instruction_fetching_emitter);
226
227 MemoryProvider memory_provider(range_check, execution_id_manager, memory_emitter);
228 CalldataHashingProvider calldata_hashing_provider(poseidon2, calldata_emitter);
229 InternalCallStackManagerProvider internal_call_stack_manager_provider(internal_call_stack_emitter);
230 ContextProvider context_provider(bytecode_manager,
231 memory_provider,
232 calldata_hashing_provider,
233 internal_call_stack_manager_provider,
234 merkle_db,
238 hints.global_variables);
240
241 // Create GetContractInstance opcode component
243 execution_id_manager, merkle_db, get_contract_instance_emitter, contract_instance_manager);
244
245 NoopDebugLogger debug_log_component;
247
249 bitwise,
250 data_copy,
251 poseidon2,
252 ecc,
253 to_radix,
254 sha256,
255 execution_components,
259 execution_emitter,
260 context_stack_emitter,
264 emit_unencrypted_log_component,
265 debug_log_component,
266 merkle_db,
268
272 merkle_db,
276 field_gt,
277 poseidon2,
280
281 tx_execution.simulate(hints.tx);
282
283 public_data_tree_check.generate_ff_gt_events_for_squashing(
284 side_effect_tracker.get_side_effects().storage_writes_slots_by_insertion);
285
286 return {
287 tx_event_emitter.dump_events(),
288 execution_emitter.dump_events(),
289 alu_emitter.dump_events(),
290 bitwise_emitter.dump_events(),
291 memory_emitter.dump_events(),
292 bytecode_retrieval_emitter.dump_events(),
293 bytecode_hashing_emitter.dump_events(),
294 bytecode_decomposition_emitter.dump_events(),
295 instruction_fetching_emitter.dump_events(),
296 address_derivation_emitter.dump_events(),
297 class_id_derivation_emitter.dump_events(),
298 siloing_emitter.dump_events(),
299 sha256_compression_emitter.dump_events(),
300 ecc_add_emitter.dump_events(),
301 scalar_mul_emitter.dump_events(),
302 ecc_add_memory_emitter.dump_events(),
303 poseidon2_hash_emitter.dump_events(),
304 poseidon2_perm_emitter.dump_events(),
305 poseidon2_perm_mem_emitter.dump_events(),
306 keccakf1600_emitter.dump_events(),
307 to_radix_emitter.dump_events(),
308 to_radix_memory_emitter.dump_events(),
309 field_gt_emitter.dump_events(),
310 greater_than_emitter.dump_events(),
311 merkle_check_emitter.dump_events(),
312 range_check_emitter.dump_events(),
313 context_stack_emitter.dump_events(),
314 public_data_tree_check_emitter.dump_events(),
315 update_check_emitter.dump_events(),
316 nullifier_tree_check_emitter.dump_events(),
317 data_copy_emitter.dump_events(),
318 calldata_emitter.dump_events(),
319 internal_call_stack_emitter.dump_events(),
320 note_hash_tree_check_emitter.dump_events(),
321 written_public_data_slots_tree_check_emitter.dump_events(),
322 contract_instance_retrieval_emitter.dump_events(),
323 get_contract_instance_emitter.dump_events(),
324 l1_to_l2_msg_tree_check_emitter.dump_events(),
325 emit_unencrypted_log_emitter.dump_events(),
326 retrieved_bytecodes_tree_check_emitter.dump_events(),
327 };
328}
329
331 LowLevelMerkleDBInterface& raw_merkle_db,
332 const PublicSimulatorConfig& config,
333 const Tx& tx,
334 const GlobalVariables& global_variables,
335 const ProtocolContracts& protocol_contracts)
336{
337 BB_BENCH_NAME("AvmSimulationHelper::simulate_fast");
338
339 NoopEventEmitter<ExecutionEvent> execution_emitter;
340 NoopEventEmitter<DataCopyEvent> data_copy_emitter;
341 NoopEventEmitter<Sha256CompressionEvent> sha256_compression_emitter;
342 NoopEventEmitter<EccAddEvent> ecc_add_emitter;
343 NoopEventEmitter<ScalarMulEvent> scalar_mul_emitter;
344 NoopEventEmitter<EccAddMemoryEvent> ecc_add_memory_emitter;
345 NoopEventEmitter<KeccakF1600Event> keccakf1600_emitter;
347 NoopEventEmitter<MerkleCheckEvent> merkle_check_emitter;
349 NoopEventEmitter<ContextStackEvent> context_stack_emitter;
351 NoopEventEmitter<CalldataEvent> calldata_emitter;
352 NoopEventEmitter<InternalCallStackEvent> internal_call_stack_emitter;
353 NoopEventEmitter<ContractInstanceRetrievalEvent> contract_instance_retrieval_emitter;
354 NoopEventEmitter<GetContractInstanceEvent> get_contract_instance_emitter;
355 NoopEventEmitter<EmitUnencryptedLogEvent> emit_unencrypted_log_emitter;
356 NoopEventEmitter<RetrievedBytecodesTreeCheckEvent> retrieved_bytecodes_tree_check_emitter;
357 NoopEventEmitter<UpdateCheckEvent> update_check_emitter;
358
365 MerkleCheck merkle_check(poseidon2, merkle_check_emitter);
368 poseidon2, merkle_check, field_gt, build_retrieved_bytecodes_tree(), retrieved_bytecodes_tree_check_emitter);
369 EmitUnencryptedLog emit_unencrypted_log_component(execution_id_manager, greater_than, emit_unencrypted_log_emitter);
370 PureAlu alu;
372 Sha256 sha256(execution_id_manager, bitwise, greater_than, sha256_compression_emitter);
374
375 Ecc ecc(execution_id_manager, greater_than, to_radix, ecc_add_emitter, scalar_mul_emitter, ecc_add_memory_emitter);
376
378 PureContractDB contract_db(raw_contract_db);
379
380 // The protocol requires at least one non-revertible nullifier in the transaction (used for uniqueness of note
381 // hashes).
382 if (tx.non_revertible_accumulated_data.nullifiers.empty()) {
383 throw std::runtime_error("Non-revertible nullifiers are empty in the transaction.");
384 }
385
387 tx.non_revertible_accumulated_data.nullifiers.at(0), raw_merkle_db, written_public_data_slots_tree_check);
389
390 tx.non_revertible_accumulated_data.nullifiers.at(0), base_merkle_db, side_effect_tracker);
391
393 if (config.collect_hints) {
394 // When collecting hints, we need to use UpdateCheck to collect required hints for storage_read.
396 poseidon2, range_check, greater_than, merkle_db, update_check_emitter, global_variables);
397 } else {
399 }
400 }();
401
403
405 contract_db, merkle_db, *update_check, field_gt, protocol_contracts, contract_instance_retrieval_emitter);
406
407 // These are needed for the TxBytecodeManager, but not for the PureTxBytecodeManager.
415 if (config.collect_hints) {
416 // When collecting hints, we need to call the contract DB to get the bytecode commitment.
417 // The pure bytecode manager doesn't do this, so we use the gadget version.
419 bytecode_hasher = std::make_unique<BytecodeHasher>(poseidon2, *bytecode_hashing_emitter);
420 bytecode_retrieval_emitter = std::make_unique<NoopEventEmitter<BytecodeRetrievalEvent>>();
421 bytecode_decomposition_emitter = std::make_unique<NoopEventEmitter<BytecodeDecompositionEvent>>();
422 instruction_fetching_emitter = std::make_unique<NoopEventEmitter<InstructionFetchingEvent>>();
424 merkle_db,
429 *bytecode_retrieval_emitter,
430 *bytecode_decomposition_emitter,
431 *instruction_fetching_emitter);
432 } else {
434 }
435 }();
436
438
439 PureMemoryProvider memory_provider;
440 CalldataHashingProvider calldata_hashing_provider(poseidon2, calldata_emitter);
441 InternalCallStackManagerProvider internal_call_stack_manager_provider(internal_call_stack_emitter);
442 ContextProvider context_provider(*tx_bytecode_manager,
443 memory_provider,
444 calldata_hashing_provider,
445 internal_call_stack_manager_provider,
446 merkle_db,
450 global_variables);
452
453 // Create GetContractInstance opcode component
455 execution_id_manager, merkle_db, get_contract_instance_emitter, contract_instance_manager);
456
458 if (config.collect_debug_logs) {
459 // TODO(fcarreiro): add debug log level?
460 const DebugLogLevel debug_log_level = DebugLogLevel::INFO;
461 return std::make_unique<DebugLogger>(debug_log_level,
463 [](const std::string& message) { info(message); });
464 } else {
466 }
467 }();
473
475 bitwise,
476 data_copy,
477 poseidon2,
478 ecc,
479 to_radix,
480 sha256,
481 execution_components,
485 execution_emitter,
486 context_stack_emitter,
490 emit_unencrypted_log_component,
491 *debug_log_component,
492 merkle_db,
497 merkle_db,
501 field_gt,
502 poseidon2,
505 config.skip_fee_enforcement);
506
508 public_inputs_builder.extract_inputs(tx, global_variables, protocol_contracts, config.prover_id, raw_merkle_db);
509
510 // This triggers all the work.
511 TxExecutionResult tx_execution_result = tx_execution.simulate(tx);
512
513 public_inputs_builder.extract_outputs(raw_merkle_db,
514 // TODO(MW): Use of billed_gas is a bit misleading - we want public + private
515 // - teardown, which is stored as billed gas here/in ts:
516 tx_execution_result.gas_used.billed_gas,
517 tx_execution_result.transaction_fee,
518 tx_execution_result.revert_code != RevertCode::OK,
519 side_effect_tracker.get_side_effects());
520
521 PublicTxEffect public_tx_effect;
522 const auto& side_effects = side_effect_tracker.get_side_effects();
523 public_tx_effect.transaction_fee = tx_execution_result.transaction_fee;
524 public_tx_effect.note_hashes = side_effects.note_hashes;
525 public_tx_effect.nullifiers = side_effects.nullifiers;
526 public_tx_effect.l2_to_l1_msgs = side_effects.l2_to_l1_messages;
527 public_tx_effect.public_logs = side_effects.public_logs.to_logs();
528 // We need to copy the storage writes slot to value in the order of the slots by insertion.
529 for (uint32_t i = 0; i < side_effects.storage_writes_slots_by_insertion.size(); i++) {
530 const auto& slot = side_effects.storage_writes_slots_by_insertion.at(i);
531 const auto& value = side_effects.storage_writes_slot_to_value.at(slot);
532 public_tx_effect.public_data_writes.push_back(PublicDataWrite{ .leaf_slot = slot, .value = value });
533 }
534
535 return {
536 // Simulation.
537 .gas_used = tx_execution_result.gas_used,
538 .revert_code = tx_execution_result.revert_code,
539 .public_tx_effect = public_tx_effect,
540 .call_stack_metadata = call_stack_metadata_collector->dump_call_stack_metadata(),
541 .logs = debug_log_component->dump_logs(),
542 // Proving request data.
543 .public_inputs =
545 .hints = std::nullopt, // NOTE: hints are injected by the caller.
546 };
547}
548
550 simulation::ContractDBInterface& raw_contract_db,
551 const world_state::WorldStateRevision& world_state_revision,
553 const PublicSimulatorConfig& config,
554 const Tx& tx,
555 const GlobalVariables& global_variables,
556 const ProtocolContracts& protocol_contracts)
557{
558 // Create PureRawMerkleDB with the provided WorldState instance
559 PureRawMerkleDB raw_merkle_db(world_state_revision, ws);
560
561 if (config.collect_hints) {
562 auto starting_tree_roots = raw_merkle_db.get_tree_roots();
564 HintingRawDB hinting_merkle_db(raw_merkle_db);
565 auto result =
566 simulate_fast(hinting_contract_db, hinting_merkle_db, config, tx, global_variables, protocol_contracts);
567 // TODO(MW): move to simulate_fast?
568 ExecutionHints collected_hints = ExecutionHints{ .global_variables = global_variables,
569 .tx = tx,
570 .protocol_contracts = protocol_contracts,
571 .starting_tree_roots = starting_tree_roots };
572 hinting_contract_db.dump_hints(collected_hints);
573 hinting_merkle_db.dump_hints(collected_hints);
574
575 result.hints = collected_hints;
576 return result;
577 };
578
579 return simulate_fast(raw_contract_db, raw_merkle_db, config, tx, global_variables, protocol_contracts);
580}
581
583{
584 // TODO(fcarreiro): decide if we want to pass a config here.
585 const PublicSimulatorConfig config{};
586
587 HintedRawContractDB raw_contract_db(hints);
588 HintedRawMerkleDB raw_merkle_db(hints);
589 return simulate_fast(
590 raw_contract_db, raw_merkle_db, config, hints.tx, hints.global_variables, hints.protocol_contracts);
591}
592
593} // namespace bb::avm2
DeduplicatingEventEmitter< FieldGreaterThanEvent > field_gt_emitter
GreaterThan greater_than
FieldGreaterThan field_gt
DeduplicatingEventEmitter< RangeCheckEvent > range_check_emitter
EventEmitter< AluEvent > alu_emitter
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:219
BytecodeHasher bytecode_hasher
StrictMock< MockHighLevelMerkleDB > merkle_db
StrictMock< MockContractDB > contract_db
StrictMock< MockContractInstanceManager > contract_instance_manager
TxSimulationResult simulate_fast_with_hinted_dbs(const ExecutionHints &hints)
TxSimulationResult simulate_fast(simulation::ContractDBInterface &raw_contract_db, simulation::LowLevelMerkleDBInterface &raw_merkle_db, const PublicSimulatorConfig &config, const Tx &tx, const GlobalVariables &global_variables, const ProtocolContracts &protocol_contracts)
simulation::EventsContainer simulate_for_witgen(const ExecutionHints &hints)
TxSimulationResult simulate_fast_with_existing_ws(simulation::ContractDBInterface &raw_contract_db, const world_state::WorldStateRevision &world_state_revision, world_state::WorldState &ws, const PublicSimulatorConfig &config, const Tx &tx, const GlobalVariables &global_variables, const ProtocolContracts &protocol_contracts)
EventEmitter< Event >::Container dump_events()
void generate_ff_gt_events_for_squashing(const std::vector< FF > &written_leaf_slots)
Generates ff_gt events for squashing.
PublicInputsBuilder & extract_inputs(const Tx &tx, const GlobalVariables &global_variables, const ProtocolContracts &protocol_contracts, const FF &prover_id, const LowLevelMerkleDBInterface &merkle_db)
TreeSnapshots get_tree_roots() const override
A high-level merkle db that tracks side effects.
Holds the Merkle trees responsible for storing the state of the Aztec protocol.
ExecutionIdManager execution_id_manager
InstructionInfoDB instruction_info_db
HintingContractsDB hinting_contract_db
HintedRawMerkleDB base_merkle_db
HintingRawDB hinting_merkle_db
crypto::Poseidon2< crypto::Poseidon2Bn254ScalarFieldParams > poseidon2
RetrievedBytecodesTree build_retrieved_bytecodes_tree()
WrittenPublicDataSlotsTree build_public_data_slots_tree()
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::vector< FF > nullifiers
Definition avm_io.hpp:319
GlobalVariables global_variables
Definition avm_io.hpp:359
ProtocolContracts protocol_contracts
Definition avm_io.hpp:362
CollectionLimitsConfig collection_limits
Definition avm_io.hpp:451
std::vector< FF > note_hashes
Definition avm_io.hpp:537
std::vector< PublicLog > public_logs
Definition avm_io.hpp:540
std::vector< FF > nullifiers
Definition avm_io.hpp:538
std::vector< PublicDataWrite > public_data_writes
Definition avm_io.hpp:541
std::vector< ScopedL2ToL1Message > l2_to_l1_msgs
Definition avm_io.hpp:539
AccumulatedData non_revertible_accumulated_data
Definition avm_io.hpp:335
tracegen::PublicInputsTraceBuilder public_inputs_builder
Definition tx.test.cpp:81
SideEffectTracker side_effect_tracker
TxExecution tx_execution
NiceMock< MockContextProvider > context_provider
NoopCallStackMetadataCollector call_stack_metadata_collector
EventEmitter< TxEvent > tx_event_emitter