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
18
19namespace bb::avm2::simulation {
20
22{
23 auto cost_in_kb = [&]() {
24 size_t total_size = 0;
25 for (const auto& instruction : std::ranges::views::values(instruction_cache)) {
26 total_size += instruction.operands.size() * sizeof(Operand);
27 }
28 return total_size / 1024;
29 };
30 vinfo("PureTxBytecodeManager held ",
31 instruction_cache.size(),
32 " instructions in cache, totaling ~",
33 cost_in_kb(),
34 " kB.");
35}
36
38{
39 BB_BENCH_NAME("PureTxBytecodeManager::get_bytecode");
40
41 // Use shared ContractInstanceManager for contract instance retrieval and validation
42 // This handles nullifier checks, address derivation, and update validation
43 auto maybe_instance = contract_instance_manager.get_contract_instance(address);
44
45 if (!maybe_instance.has_value()) {
46 vinfo("Contract ", field_to_string(address), " is not deployed!");
47 throw BytecodeRetrievalError("Contract " + field_to_string(address) + " is not deployed");
48 }
49
50 ContractInstance instance = maybe_instance.value();
52
53 bool is_new_class = !retrieved_class_ids.contains(current_class_id);
54 size_t retrieved_bytecodes_count = retrieved_class_ids.size();
55
56 if (is_new_class && retrieved_bytecodes_count >= MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS) {
57 throw BytecodeRetrievalError("Can't retrieve more than " +
59 " bytecodes per tx");
60 }
61
63
64 // Contract class retrieval and class ID validation
66 // Note: we don't need to silo and check the class id because the deployer contract guarrantees
67 // that if a contract instance exists, the class has been registered.
68 assert(maybe_klass.has_value());
69 auto& klass = maybe_klass.value();
70 debug("Bytecode for ", address, " successfully retrieved!");
71
72 // Bytecode hashing and decomposition, deduplicated by bytecode_id (commitment)
73 BytecodeId bytecode_id = klass.public_bytecode_commitment;
74
75 // Check if we've already processed this bytecode.
76 if (bytecodes.contains(bytecode_id)) {
77 return bytecode_id;
78 }
79
80 // We now save the bytecode so that we don't repeat this process.
81 bytecodes[bytecode_id] = std::make_shared<std::vector<uint8_t>>(std::move(klass.packed_bytecode));
82 return bytecode_id;
83}
84
86{
87 // The corresponding bytecode is already stored in the cache if we call this routine. This is safe-guarded by the
88 // fact that it is added in the cache when we retrieve the bytecode_id.
89 return read_instruction(bytecode_id, get_bytecode_data(bytecode_id), pc);
90}
91
93 std::shared_ptr<std::vector<uint8_t>> bytecode_ptr,
94 uint32_t pc)
95{
96 BB_BENCH_NAME("TxBytecodeManager::read_instruction");
97
98 // Try to get the instruction from the cache.
99 InstructionIdentifier instruction_identifier = { bytecode_ptr.get(), pc };
100 auto it = instruction_cache.find(instruction_identifier);
101 if (it != instruction_cache.end()) {
102 return it->second;
103 }
104
105 // If not found, deserialize the instruction, etc.
106 const auto& bytecode = *bytecode_ptr;
108
109 try {
110 instruction = deserialize_instruction(bytecode, pc);
111 } catch (const InstrDeserializationError& error) {
112 throw InstructionFetchingError("Instruction fetching error: " + std::to_string(static_cast<int>(error)));
113 }
114
115 // If the following code is executed, no error was thrown in deserialize_instruction().
116 if (!check_tag(instruction)) {
117 throw InstructionFetchingError("Tag check failed");
118 };
119
120 // Save the instruction to the cache.
121 instruction_cache.emplace(instruction_identifier, instruction);
122 return instruction;
123}
124
129
130} // namespace bb::avm2::simulation
#define MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS
#define BB_BENCH_NAME(name)
Definition bb_bench.hpp:218
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
Instruction read_instruction(const BytecodeId &bytecode_id, uint32_t pc) override
BytecodeId get_bytecode(const AztecAddress &address) override
unordered_flat_map< BytecodeId, std::shared_ptr< std::vector< uint8_t > > > bytecodes
unordered_flat_set< ContractClassId > retrieved_class_ids
std::tuple< void *, uint32_t > InstructionIdentifier
unordered_flat_map< InstructionIdentifier, Instruction > instruction_cache
#define vinfo(...)
Definition log.hpp:79
#define debug(...)
Definition log.hpp:61
Instruction instruction
bool check_tag(const Instruction &instruction)
Check whether the instruction must have a tag operand and whether the operand value is in the value t...
Instruction deserialize_instruction(std::span< const uint8_t > bytecode, size_t pos)
Parsing of an instruction in the supplied bytecode at byte position pos. This checks that the WireOpC...
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
ContractClassId current_class_id