Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
pure_bytecode_manager.cpp
Go to the documentation of this file.
2
3#include <cassert>
4
14
15namespace bb::avm2::simulation {
16
18{
19 auto cost_in_kb = [&]() {
20 size_t total_size = 0;
21 for (const auto& instruction : std::ranges::views::values(instruction_cache)) {
22 total_size += instruction.operands.size() * sizeof(Operand);
23 }
24 return total_size / 1024;
25 };
26 vinfo("PureTxBytecodeManager held ",
27 instruction_cache.size(),
28 " instructions in cache, totaling ~",
29 cost_in_kb(),
30 " kB.");
31}
32
51{
52 BB_BENCH_NAME("PureTxBytecodeManager::get_bytecode");
53
54 // Use shared ContractInstanceManager for contract instance retrieval and validation
55 // This handles nullifier checks, address derivation, and update validation
57
58 if (!maybe_instance.has_value()) {
59 vinfo("Contract ", field_to_string(address), " is not deployed!");
60 throw BytecodeRetrievalError("Contract " + field_to_string(address) + " is not deployed");
61 }
62
63 ContractInstance instance = maybe_instance.value();
64 ContractClassId current_class_id = instance.current_contract_class_id;
65
66 bool is_new_class = !retrieved_class_ids.contains(current_class_id);
67 size_t retrieved_bytecodes_count = retrieved_class_ids.size();
68
69 if (is_new_class && retrieved_bytecodes_count >= MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS) {
70 throw BytecodeRetrievalError("Can't retrieve more than " +
72 " bytecodes per tx");
73 }
74
76
77 // For fast simulation, we use the class_id as the bytecode_id instead of computing the
78 // expensive bytecode commitment hash. This is safe because class_id uniquely identifies
79 // the bytecode. The actual commitment is only needed for trace generation / witgen.
80 BytecodeId bytecode_id = current_class_id;
81
82 // Check if we've already processed this class id.
83 // NOTE: If two different classes have the same bytecode, we cannot deduplicate them.
84 // This is the downside of using the class id as the bytecode id.
85 if (bytecodes.contains(bytecode_id)) {
86 return bytecode_id;
87 }
88
89 // Contract class retrieval and class ID validation
90
92 // Note: we don't need to silo and check the class id because the deployer contract guarantees
93 // that if a contract instance exists, the class has been registered.
94 BB_ASSERT(maybe_klass.has_value(), "Contract class not found");
95 auto& klass = maybe_klass.value();
96 debug("Bytecode for ", address, " successfully retrieved!");
97
98 // We now save the bytecode against the class id so that we don't repeat this process for the same class.
99 bytecodes[bytecode_id] = std::make_shared<std::vector<uint8_t>>(std::move(klass.packed_bytecode));
100
101 return bytecode_id;
102}
103
117{
118 // The corresponding bytecode is already stored in the cache if we call this routine. This is safe-guarded by the
119 // fact that it is added in the cache when we retrieve the bytecode_id.
120 return read_instruction(bytecode_id, get_bytecode_data(bytecode_id), pc);
121}
122
145 std::shared_ptr<std::vector<uint8_t>> bytecode_ptr,
146 PC pc)
147{
148 BB_BENCH_NAME("TxBytecodeManager::read_instruction");
149
150 // Try to get the instruction from the cache.
151 InstructionIdentifier instruction_identifier = { bytecode_ptr.get(), pc };
152 auto it = instruction_cache.find(instruction_identifier);
153 if (it != instruction_cache.end()) {
154 return it->second;
155 }
156
157 // If not found, deserialize the instruction, etc.
158 const auto& bytecode = *bytecode_ptr;
160
161 try {
163 } catch (const InstrDeserializationError& error) {
164 std::string error_msg = format("Instruction fetching error at pc ", pc);
165 if (error.message.has_value()) {
166 error_msg = format(error_msg, ": ", error.message.value());
167 }
168 throw InstructionFetchingError(error_msg);
169 }
170
171 // If the following code is executed, no error was thrown in deserialize_instruction().
172 if (!check_tag(instruction)) {
173 std::string error_msg = format("Instruction fetching error at pc ", pc, ": Tag check failed");
174 throw InstructionFetchingError(error_msg);
175 };
176
177 // Save the instruction to the cache.
178 instruction_cache.emplace(instruction_identifier, instruction);
179 return instruction;
180}
181
183{
184 auto it = bytecodes.find(bytecode_id);
185 BB_ASSERT_DEBUG(it != bytecodes.end(), "Bytecode not found for the given bytecode_id");
186 return it->second;
187}
188
189} // namespace bb::avm2::simulation
#define BB_ASSERT(expression,...)
Definition assert.hpp:70
#define BB_ASSERT_DEBUG(expression,...)
Definition assert.hpp:55
std::shared_ptr< Napi::ThreadSafeFunction > instance
std::shared_ptr< Napi::ThreadSafeFunction > bytecode
#define MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:264
virtual std::optional< ContractClass > get_contract_class(const ContractClassId &class_id) const =0
virtual std::optional< ContractInstance > get_contract_instance(const FF &contract_address)=0
Retrieve and validate a contract instance.
ContractInstanceManagerInterface & contract_instance_manager
std::shared_ptr< std::vector< uint8_t > > get_bytecode_data(const BytecodeId &bytecode_id) override
BytecodeId get_bytecode(const AztecAddress &address) override
Retrieves and validates bytecode from the PureTxBytecodeManager's ContractDBInterface.
unordered_flat_map< BytecodeId, std::shared_ptr< std::vector< uint8_t > > > bytecodes
Instruction read_instruction(const BytecodeId &bytecode_id, PC pc) override
Reads and deserializes the instruction given by the pair [ bytecode_id, pc ]. Corresponds to instr_fe...
unordered_flat_set< ContractClassId > retrieved_class_ids
unordered_flat_map< InstructionIdentifier, Instruction > instruction_cache
std::string format(Args... args)
Definition log.hpp:23
#define vinfo(...)
Definition log.hpp:94
#define debug(...)
Definition log.hpp:99
Instruction instruction
AVM range check gadget for witness generation.
bool check_tag(const Instruction &instruction)
Checks whether the tag operand of an instruction is a valid MemoryTag. Called by bytecode managers du...
Instruction deserialize_instruction(std::span< const uint8_t > bytecode, size_t pos)
Attempts to deserialize the instruction at position pos in bytecode. Called by bytecode managers duri...
uint32_t PC
FF ContractClassId
std::string field_to_string(const FF &ff)
Definition stringify.cpp:5
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
FF current_class_id