diff --git a/barretenberg/cpp/src/barretenberg/vm2/common/aztec_types.hpp b/barretenberg/cpp/src/barretenberg/vm2/common/aztec_types.hpp index 36603ef4e7a7..81bb2c76d47f 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/common/aztec_types.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/common/aztec_types.hpp @@ -16,6 +16,12 @@ struct PublicKeys { AffinePoint incoming_viewing_key; AffinePoint outgoing_viewing_key; AffinePoint tagging_key; + + std::vector to_fields() const + { + return { nullifier_key.x, nullifier_key.y, incoming_viewing_key.x, incoming_viewing_key.y, + outgoing_viewing_key.x, outgoing_viewing_key.y, tagging_key.x, tagging_key.y }; + } }; struct ContractInstance { diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/address_derivation.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/address_derivation.cpp new file mode 100644 index 000000000000..ec689ef1d6a2 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/address_derivation.cpp @@ -0,0 +1,18 @@ +#include "barretenberg/vm2/simulation/address_derivation.hpp" + +#include + +#include "barretenberg/vm/aztec_constants.hpp" +#include "barretenberg/vm2/simulation/lib/contract_crypto.hpp" + +namespace bb::avm2::simulation { + +void AddressDerivation::assert_derivation(const AztecAddress& address, const ContractInstance& instance) +{ + // TODO: Cache and deduplicate. + // TODO: Use gadget. + assert(compute_contract_address(instance) == address); + events.emit({ .address = address, .instance = instance }); +} + +} // namespace bb::avm2::simulation \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/address_derivation.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/address_derivation.hpp new file mode 100644 index 000000000000..e751723157e5 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/address_derivation.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "barretenberg/vm2/common/aztec_types.hpp" +#include "barretenberg/vm2/simulation/events/address_derivation_event.hpp" +#include "barretenberg/vm2/simulation/events/event_emitter.hpp" + +namespace bb::avm2::simulation { + +class AddressDerivationInterface { + public: + virtual ~AddressDerivationInterface() = default; + virtual void assert_derivation(const AztecAddress& address, const ContractInstance& instance) = 0; +}; + +class AddressDerivation : public AddressDerivationInterface { + public: + AddressDerivation(EventEmitterInterface& events) + : events(events) + {} + + void assert_derivation(const AztecAddress& address, const ContractInstance& instance) override; + + private: + EventEmitterInterface& events; +}; + +} // namespace bb::avm2::simulation \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/bytecode_manager.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/bytecode_manager.cpp index 3a4ebd71f7bf..6a17a809fe65 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/bytecode_manager.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/bytecode_manager.cpp @@ -17,7 +17,9 @@ BytecodeId TxBytecodeManager::get_bytecode(const AztecAddress& address) // TODO: catch errors etc. // TODO: we should trigger the proper merkle checks etc. The raw DB doesn't. ContractInstance instance = db.get_contract_instance(address); + address_derivation.assert_derivation(address, instance); ContractClass klass = db.get_contract_class(instance.contract_class_id); + class_id_derivation.assert_derivation(instance.contract_class_id, klass); auto bytecode_id = next_bytecode_id++; info("Bytecode for ", address, " successfully retrieved!"); diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/bytecode_manager.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/bytecode_manager.hpp index 4fc17ebad531..73ffb1928bbd 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/bytecode_manager.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/bytecode_manager.hpp @@ -9,10 +9,13 @@ #include "barretenberg/vm2/common/aztec_types.hpp" #include "barretenberg/vm2/common/map.hpp" +#include "barretenberg/vm2/simulation/address_derivation.hpp" +#include "barretenberg/vm2/simulation/class_id_derivation.hpp" #include "barretenberg/vm2/simulation/events/bytecode_events.hpp" #include "barretenberg/vm2/simulation/events/event_emitter.hpp" #include "barretenberg/vm2/simulation/lib/raw_data_db.hpp" #include "barretenberg/vm2/simulation/lib/serialization.hpp" +#include "barretenberg/vm2/simulation/siloing.hpp" namespace bb::avm2::simulation { @@ -33,10 +36,14 @@ class TxBytecodeManagerInterface { class TxBytecodeManager : public TxBytecodeManagerInterface { public: TxBytecodeManager(RawDataDBInterface& db, + AddressDerivationInterface& address_derivation, + ClassIdDerivationInterface& class_id_derivation, EventEmitterInterface& retrieval_events, EventEmitterInterface& hash_events, EventEmitterInterface& decomposition_events) : db(db) + , address_derivation(address_derivation) + , class_id_derivation(class_id_derivation) , retrieval_events(retrieval_events) , hash_events(hash_events) , decomposition_events(decomposition_events) @@ -47,6 +54,8 @@ class TxBytecodeManager : public TxBytecodeManagerInterface { private: RawDataDBInterface& db; + AddressDerivationInterface& address_derivation; + ClassIdDerivationInterface& class_id_derivation; EventEmitterInterface& retrieval_events; EventEmitterInterface& hash_events; EventEmitterInterface& decomposition_events; diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/class_id_derivation.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/class_id_derivation.cpp new file mode 100644 index 000000000000..8efd8115f724 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/class_id_derivation.cpp @@ -0,0 +1,19 @@ +#include "barretenberg/vm2/simulation/class_id_derivation.hpp" + +#include + +#include "barretenberg/vm/aztec_constants.hpp" +#include "barretenberg/vm2/simulation/lib/contract_crypto.hpp" + +namespace bb::avm2::simulation { + +void ClassIdDerivation::assert_derivation(const ContractClassId& class_id, const ContractClass& klass) +{ + // TODO: Cache and deduplicate. + // TODO: Use gadget. + assert(compute_contract_class_id( + klass.artifact_hash, klass.private_function_root, klass.public_bytecode_commitment) == class_id); + events.emit({ .class_id = class_id, .klass = klass }); +} + +} // namespace bb::avm2::simulation \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/class_id_derivation.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/class_id_derivation.hpp new file mode 100644 index 000000000000..6e5e960994a8 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/class_id_derivation.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "barretenberg/vm2/common/aztec_types.hpp" +#include "barretenberg/vm2/simulation/events/class_id_derivation_event.hpp" +#include "barretenberg/vm2/simulation/events/event_emitter.hpp" + +namespace bb::avm2::simulation { + +class ClassIdDerivationInterface { + public: + virtual ~ClassIdDerivationInterface() = default; + virtual void assert_derivation(const ContractClassId& class_id, const ContractClass& klass) = 0; +}; + +class ClassIdDerivation : public ClassIdDerivationInterface { + public: + ClassIdDerivation(EventEmitterInterface& events) + : events(events) + {} + + void assert_derivation(const ContractClassId& class_id, const ContractClass& klass) override; + + private: + EventEmitterInterface& events; +}; + +} // namespace bb::avm2::simulation \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/events/address_derivation_event.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/events/address_derivation_event.hpp new file mode 100644 index 000000000000..06c191510541 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/events/address_derivation_event.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "barretenberg/vm2/common/aztec_types.hpp" + +namespace bb::avm2::simulation { + +struct AddressDerivationEvent { + AztecAddress address; + ContractInstance instance; +}; + +} // namespace bb::avm2::simulation \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/events/class_id_derivation_event.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/events/class_id_derivation_event.hpp new file mode 100644 index 000000000000..6514d64965bb --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/events/class_id_derivation_event.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "barretenberg/vm2/common/aztec_types.hpp" + +namespace bb::avm2::simulation { + +struct ClassIdDerivationEvent { + ContractClassId class_id; + // WARNING: this class has the whole bytecode. Create a new class. + ContractClass klass; +}; + +} // namespace bb::avm2::simulation \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/events/events_container.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/events/events_container.hpp index c1e02ee2a07a..d45d5556dd5c 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/events/events_container.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/events/events_container.hpp @@ -1,11 +1,14 @@ #pragma once +#include "barretenberg/vm2/simulation/events/address_derivation_event.hpp" #include "barretenberg/vm2/simulation/events/addressing_event.hpp" #include "barretenberg/vm2/simulation/events/alu_event.hpp" #include "barretenberg/vm2/simulation/events/bytecode_events.hpp" +#include "barretenberg/vm2/simulation/events/class_id_derivation_event.hpp" #include "barretenberg/vm2/simulation/events/event_emitter.hpp" #include "barretenberg/vm2/simulation/events/execution_event.hpp" #include "barretenberg/vm2/simulation/events/memory_event.hpp" +#include "barretenberg/vm2/simulation/events/siloing_event.hpp" namespace bb::avm2::simulation { @@ -17,6 +20,9 @@ struct EventsContainer { EventEmitterInterface::Container bytecode_retrieval; EventEmitterInterface::Container bytecode_hashing; EventEmitterInterface::Container bytecode_decomposition; + EventEmitterInterface::Container address_derivation; + EventEmitterInterface::Container class_id_derivation; + EventEmitterInterface::Container siloing; }; } // namespace bb::avm2::simulation \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/events/siloing_event.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/events/siloing_event.hpp new file mode 100644 index 000000000000..50f4efccb3a6 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/events/siloing_event.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "barretenberg/vm2/common/field.hpp" + +namespace bb::avm2::simulation { + +enum class SiloingType { NULLIFIER }; + +struct SiloingEvent { + SiloingType type; + FF elem; + FF siloed_by; + FF siloed_elem; +}; + +} // namespace bb::avm2::simulation \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/contract_crypto.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/contract_crypto.cpp index 281a927d75bc..c923c27b43a9 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/contract_crypto.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/contract_crypto.cpp @@ -41,4 +41,29 @@ FF compute_contract_class_id(const FF& artifact_hash, const FF& private_fn_root, { GENERATOR_INDEX__CONTRACT_LEAF, artifact_hash, private_fn_root, public_bytecode_commitment }); } +FF compute_contract_address(const ContractInstance& contract_instance) +{ + FF salted_initialization_hash = poseidon2::hash({ GENERATOR_INDEX__PARTIAL_ADDRESS, + contract_instance.salt, + contract_instance.initialisation_hash, + contract_instance.deployer_addr }); + FF partial_address = poseidon2::hash( + { GENERATOR_INDEX__PARTIAL_ADDRESS, contract_instance.contract_class_id, salted_initialization_hash }); + + std::vector public_keys_hash_fields = contract_instance.public_keys.to_fields(); + std::vector public_key_hash_vec{ GENERATOR_INDEX__PUBLIC_KEYS_HASH }; + for (size_t i = 0; i < public_keys_hash_fields.size(); i += 2) { + public_key_hash_vec.push_back(public_keys_hash_fields[i]); + public_key_hash_vec.push_back(public_keys_hash_fields[i + 1]); + // Is it guaranteed we wont get a point at infinity here? + public_key_hash_vec.push_back(FF::zero()); + } + FF public_keys_hash = poseidon2::hash({ public_key_hash_vec }); + + FF h = poseidon2::hash({ GENERATOR_INDEX__CONTRACT_ADDRESS_V1, public_keys_hash, partial_address }); + // This is safe since BN254_Fr < GRUMPKIN_Fr so we know there is no modulo reduction + grumpkin::fr h_fq = grumpkin::fr(h); + return (grumpkin::g1::affine_one * h_fq + contract_instance.public_keys.incoming_viewing_key).x; +} + } // namespace bb::avm2::simulation \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/contract_crypto.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/contract_crypto.hpp index d7fa771e9e34..7197d2848e6a 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/contract_crypto.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/contract_crypto.hpp @@ -3,11 +3,13 @@ #include #include +#include "barretenberg/vm2/common/aztec_types.hpp" #include "barretenberg/vm2/common/field.hpp" namespace bb::avm2::simulation { FF compute_public_bytecode_commitment(std::span bytecode); FF compute_contract_class_id(const FF& artifact_hash, const FF& private_fn_root, const FF& public_bytecode_commitment); +FF compute_contract_address(const ContractInstance& contract_instance); } // namespace bb::avm2::simulation \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/memory.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/memory.cpp index 811ebfbb32b2..16a34cd746b3 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/memory.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/memory.cpp @@ -1,10 +1,10 @@ #include "barretenberg/vm2/simulation/memory.hpp" -#include "barretenberg/common/log.hpp" -#include "barretenberg/vm2/common/memory_types.hpp" #include #include -#include + +#include "barretenberg/common/log.hpp" +#include "barretenberg/vm2/common/memory_types.hpp" namespace bb::avm2::simulation { diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/memory.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/memory.hpp index 5e9ada80a5e6..fef424876554 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/memory.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/memory.hpp @@ -1,8 +1,8 @@ #pragma once #include -#include +#include "barretenberg/vm2/common/map.hpp" #include "barretenberg/vm2/common/memory_types.hpp" #include "barretenberg/vm2/simulation/events/event_emitter.hpp" #include "barretenberg/vm2/simulation/events/memory_event.hpp" @@ -50,7 +50,7 @@ class Memory : public MemoryInterface { }; uint32_t space_id; - std::unordered_map memory; + unordered_flat_map memory; EventEmitterInterface& events; }; diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/siloing.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/siloing.cpp new file mode 100644 index 000000000000..bfbbb2f0621c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/siloing.cpp @@ -0,0 +1,20 @@ +#include "barretenberg/vm2/simulation/siloing.hpp" + +#include "barretenberg/crypto/poseidon2/poseidon2.hpp" +#include "barretenberg/vm/aztec_constants.hpp" +#include "barretenberg/vm2/simulation/events/siloing_event.hpp" + +namespace bb::avm2::simulation { + +using Poseidon2 = crypto::Poseidon2; + +FF Siloing::silo(const FF& generator, const FF& elem, const FF& silo_by, SiloingType type) +{ + // TODO: Cache and deduplicate. + // TODO: Use poseidon gadget. + auto siloed_elem = Poseidon2::hash({ generator, silo_by, elem }); + events.emit({ .type = type, .elem = elem, .siloed_by = silo_by, .siloed_elem = siloed_elem }); + return siloed_elem; +} + +} // namespace bb::avm2::simulation \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/siloing.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/siloing.hpp new file mode 100644 index 000000000000..eaf0dfe1bb70 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/siloing.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "barretenberg/vm/aztec_constants.hpp" +#include "barretenberg/vm2/common/field.hpp" +#include "barretenberg/vm2/simulation/events/event_emitter.hpp" +#include "barretenberg/vm2/simulation/events/siloing_event.hpp" + +namespace bb::avm2::simulation { + +class SiloingInterface { + public: + virtual ~SiloingInterface() = default; + virtual FF silo_nullifier(const FF& nullifier, const FF& silo_by) = 0; +}; + +class Siloing : public SiloingInterface { + public: + Siloing(EventEmitterInterface& events) + : events(events) + {} + + FF silo_nullifier(const FF& nullifier, const FF& silo_by) override + { + return silo(GENERATOR_INDEX__OUTER_NULLIFIER, nullifier, silo_by, SiloingType::NULLIFIER); + } + + private: + FF silo(const FF& generator, const FF& elem, const FF& silo_by, SiloingType type); + + EventEmitterInterface& events; +}; + +} // namespace bb::avm2::simulation \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation_helper.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation_helper.cpp index 620ef0b362f4..cff0c929280f 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation_helper.cpp @@ -1,8 +1,5 @@ #include "barretenberg/vm2/simulation_helper.hpp" -#include -#include - #include "barretenberg/common/log.hpp" #include "barretenberg/vm2/common/avm_inputs.hpp" #include "barretenberg/vm2/common/aztec_types.hpp" @@ -15,6 +12,7 @@ #include "barretenberg/vm2/simulation/execution.hpp" #include "barretenberg/vm2/simulation/lib/instruction_info.hpp" #include "barretenberg/vm2/simulation/lib/raw_data_db.hpp" +#include "barretenberg/vm2/simulation/siloing.hpp" #include "barretenberg/vm2/simulation/tx_execution.hpp" namespace bb::avm2 { @@ -32,6 +30,9 @@ struct ProvingSettings { using BytecodeRetrievalEventEmitter = EventEmitter; using BytecodeHashingEventEmitter = EventEmitter; using BytecodeDecompositionEventEmitter = EventEmitter; + using AddressDerivationEventEmitter = EventEmitter; + using ClassIdDerivationEventEmitter = EventEmitter; + using SiloingEventEmitter = EventEmitter; }; // Configuration for fast simulation. @@ -43,7 +44,9 @@ struct FastSettings { using BytecodeRetrievalEventEmitter = NoopEventEmitter; using BytecodeHashingEventEmitter = NoopEventEmitter; using BytecodeDecompositionEventEmitter = NoopEventEmitter; - // Customization can go here, for example a BytecodeManager that does NOT hash bytecodes. + using AddressDerivationEventEmitter = NoopEventEmitter; + using ClassIdDerivationEventEmitter = NoopEventEmitter; + using SiloingEventEmitter = NoopEventEmitter; }; } // namespace @@ -57,10 +60,22 @@ template EventsContainer AvmSimulationHelper::simulate_with_setting typename S::BytecodeRetrievalEventEmitter bytecode_retrieval_emitter; typename S::BytecodeHashingEventEmitter bytecode_hashing_emitter; typename S::BytecodeDecompositionEventEmitter bytecode_decomposition_emitter; + typename S::AddressDerivationEventEmitter address_derivation_emitter; + typename S::ClassIdDerivationEventEmitter class_id_derivation_emitter; + typename S::SiloingEventEmitter siloing_emitter; HintedRawDataDB db(inputs.hints); - TxBytecodeManager bytecode_manager( - db, bytecode_retrieval_emitter, bytecode_hashing_emitter, bytecode_decomposition_emitter); + AddressDerivation address_derivation(address_derivation_emitter); + ClassIdDerivation class_id_derivation(class_id_derivation_emitter); + Siloing siloing(siloing_emitter); + // TODO: I'm not using the siloing gadget yet here. + // It should probably not be in bytecode_manager, but in sth related to the contract instance. + TxBytecodeManager bytecode_manager(db, + address_derivation, + class_id_derivation, + bytecode_retrieval_emitter, + bytecode_hashing_emitter, + bytecode_decomposition_emitter); ContextProvider context_provider(bytecode_manager, memory_emitter); Alu alu(alu_emitter); @@ -78,7 +93,10 @@ template EventsContainer AvmSimulationHelper::simulate_with_setting addressing_emitter.dump_events(), bytecode_retrieval_emitter.dump_events(), bytecode_hashing_emitter.dump_events(), - bytecode_decomposition_emitter.dump_events() }; + bytecode_decomposition_emitter.dump_events(), + address_derivation_emitter.dump_events(), + class_id_derivation_emitter.dump_events(), + siloing_emitter.dump_events() }; } EventsContainer AvmSimulationHelper::simulate()