Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions barretenberg/cpp/pil/vm2/context.pil
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,10 @@ namespace execution;

pol commit is_static;
is_static * (1 - is_static) = 0;

pol commit parent_calldata_offset_addr;
pol commit parent_calldata_size_addr;

pol commit last_child_returndata_offset_addr;
pol commit last_child_returndata_size_addr;
pol commit last_child_success; // Careful with this for now...
3 changes: 3 additions & 0 deletions barretenberg/cpp/pil/vm2/context_stack.pil
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ namespace context_stack;

pol commit is_static;
is_static * (1 - is_static) = 0;

pol commit parent_calldata_offset_addr;
pol commit parent_calldata_size_addr;
6 changes: 3 additions & 3 deletions barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions barretenberg/cpp/src/barretenberg/vm2/generated/flavor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,12 @@ class AvmFlavor {
static constexpr bool HasZK = false;

static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 47;
static constexpr size_t NUM_WITNESS_ENTITIES = 929;
static constexpr size_t NUM_WITNESS_ENTITIES = 936;
static constexpr size_t NUM_SHIFTED_ENTITIES = 134;
static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES;
// We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for
// the unshifted and one for the shifted
static constexpr size_t NUM_ALL_ENTITIES = 1110;
static constexpr size_t NUM_ALL_ENTITIES = 1117;

// In the sumcheck univariate computation, we divide the trace in chunks and each chunk is
// evenly processed by all the threads. This constant defines the maximum number of rows
Expand Down
178 changes: 131 additions & 47 deletions barretenberg/cpp/src/barretenberg/vm2/simulation/context.hpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#pragma once

#include <algorithm>
#include <cstdint>
#include <memory>
#include <span>
#include <vector>

#include "barretenberg/vm2/common/aztec_types.hpp"
#include "barretenberg/vm2/common/field.hpp"
#include "barretenberg/vm2/common/memory_types.hpp"
#include "barretenberg/vm2/simulation/bytecode_manager.hpp"
#include "barretenberg/vm2/simulation/events/context_events.hpp"
#include "barretenberg/vm2/simulation/events/event_emitter.hpp"
Expand All @@ -26,7 +28,6 @@ class ContextInterface {
virtual void set_pc(uint32_t new_pc) = 0;
virtual uint32_t get_next_pc() const = 0;
virtual void set_next_pc(uint32_t new_next_pc) = 0;
virtual void set_nested_returndata(std::vector<FF> return_data) = 0;
virtual bool halted() const = 0;
virtual void halt() = 0;

Expand All @@ -35,12 +36,28 @@ class ContextInterface {
// Environment.
virtual const AztecAddress& get_address() const = 0;
virtual const AztecAddress& get_msg_sender() const = 0;
virtual std::span<const FF> get_calldata() const = 0;
virtual bool get_is_static() const = 0;

// Input / Output
virtual std::vector<FF> get_calldata(uint32_t cd_offset, uint32_t cd_size) const = 0;
virtual std::vector<FF> get_returndata(uint32_t rd_offset, uint32_t rd_size) = 0;
virtual ContextInterface& get_child_context() = 0;
// The child context needs to be accessible by this context in order to access the child
// memory for returndata. We own it so that it's lifetime is as long as decided by this context
// (i.e. if it is replaced by another child OR this parent context falls out of scope)
virtual void set_child_context(std::unique_ptr<ContextInterface> child_ctx) = 0;

virtual MemoryAddress get_last_rd_offset() const = 0;
virtual void set_last_rd_offset(MemoryAddress rd_offset) = 0;

virtual MemoryAddress get_last_rd_size() const = 0;
virtual void set_last_rd_size(MemoryAddress rd_size) = 0;

virtual bool get_last_success() const = 0;
virtual void set_last_success(bool success) = 0;

// Events
virtual void emit_context_snapshot() = 0;
virtual ContextEvent get_current_context() = 0;
virtual ContextEvent serialize_context_event() = 0;
};

// The context for a single nested call.
Expand All @@ -49,19 +66,15 @@ class BaseContext : public ContextInterface {
BaseContext(uint32_t context_id,
AztecAddress address,
AztecAddress msg_sender,
std::span<const FF> calldata,
bool is_static,
std::unique_ptr<BytecodeManagerInterface> bytecode,
std::unique_ptr<MemoryInterface> memory,
EventEmitterInterface<ContextStackEvent>& ctx_stack_events)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Migrated to Execution - feels better

std::unique_ptr<MemoryInterface> memory)
: address(address)
, msg_sender(msg_sender)
, calldata(calldata.begin(), calldata.end())
, is_static(is_static)
, context_id(context_id)
, bytecode(std::move(bytecode))
, memory(std::move(memory))
, ctx_stack_events(ctx_stack_events)
{}

// Having getters and setters make it easier to mock the context.
Expand All @@ -72,7 +85,6 @@ class BaseContext : public ContextInterface {
void set_pc(uint32_t new_pc) override { pc = new_pc; }
uint32_t get_next_pc() const override { return next_pc; }
void set_next_pc(uint32_t new_next_pc) override { next_pc = new_next_pc; }
void set_nested_returndata(std::vector<FF> return_data) override { nested_returndata = std::move(return_data); }
bool halted() const override { return has_halted; }
void halt() override { has_halted = true; }

Expand All @@ -81,31 +93,42 @@ class BaseContext : public ContextInterface {
// Environment.
const AztecAddress& get_address() const override { return address; }
const AztecAddress& get_msg_sender() const override { return msg_sender; }
std::span<const FF> get_calldata() const override { return calldata; }
bool get_is_static() const override { return is_static; }

// Event Emitting
void emit_context_snapshot() override
ContextInterface& get_child_context() override { return *child_context; }
void set_child_context(std::unique_ptr<ContextInterface> child_ctx) override
{
ctx_stack_events.emit({ .id = context_id,
.next_pc = next_pc,
.msg_sender = msg_sender,
.contract_addr = address,
.is_static = is_static });
};
child_context = std::move(child_ctx);
}

MemoryAddress get_last_rd_offset() const override { return last_child_rd_offset; }
void set_last_rd_offset(MemoryAddress rd_offset) override { last_child_rd_offset = rd_offset; }

MemoryAddress get_last_rd_size() const override { return last_child_rd_size; }
void set_last_rd_size(MemoryAddress rd_size) override { last_child_rd_size = rd_size; }

bool get_last_success() const override { return last_child_success; }
void set_last_success(bool success) override { last_child_success = success; }

ContextEvent get_current_context() override
// Input / Output
std::vector<FF> get_returndata(uint32_t rd_offset, uint32_t rd_size) override
{
return {
.id = context_id, .pc = pc, .msg_sender = msg_sender, .contract_addr = address, .is_static = is_static
};
MemoryInterface& child_memory = get_child_context().get_memory();
auto get_returndata_size = child_memory.get(last_child_rd_size);
uint32_t returndata_size = static_cast<uint32_t>(get_returndata_size.value);
uint32_t write_size = std::min(rd_offset + rd_size, returndata_size);

std::vector<FF> retrieved_returndata =
child_memory.get_slice(get_last_rd_offset() + rd_offset, write_size).first;
retrieved_returndata.resize(rd_size);

return retrieved_returndata;
};

private:
// Environment.
AztecAddress address;
AztecAddress msg_sender;
std::vector<FF> calldata;
bool is_static;

uint32_t context_id;
Expand All @@ -114,12 +137,14 @@ class BaseContext : public ContextInterface {
uint32_t pc = 0;
uint32_t next_pc = 0;
bool has_halted = false;
std::vector<FF> nested_returndata;
std::unique_ptr<BytecodeManagerInterface> bytecode;
std::unique_ptr<MemoryInterface> memory;

// Emiiters
EventEmitterInterface<ContextStackEvent>& ctx_stack_events;
// Output
std::unique_ptr<ContextInterface> child_context = nullptr;
MemoryAddress last_child_rd_offset = 0;
MemoryAddress last_child_rd_size = 0;
bool last_child_success = false;
};

// TODO(ilyas): flesh these out in the cpp file, these are just temporary
Expand All @@ -128,20 +153,47 @@ class EnqueuedCallContext : public BaseContext {
EnqueuedCallContext(uint32_t context_id,
AztecAddress address,
AztecAddress msg_sender,
std::span<const FF> calldata,
bool is_static,
std::unique_ptr<BytecodeManagerInterface> bytecode,
std::unique_ptr<MemoryInterface> memory,
EventEmitterInterface<ContextStackEvent>& ctx_stack_events)
: BaseContext(context_id,
address,
msg_sender,
calldata,
is_static,
std::move(bytecode),
std::move(memory),
ctx_stack_events)
std::span<const FF> calldata)
: BaseContext(context_id, address, msg_sender, is_static, std::move(bytecode), std::move(memory))
, calldata(calldata.begin(), calldata.end())
{}

// Event Emitting
ContextEvent serialize_context_event() override
{
return { .id = get_context_id(),
.pc = get_pc(),
.msg_sender = get_msg_sender(),
.contract_addr = get_address(),
.is_static = get_is_static(),
.parent_cd_addr = 0,
.parent_cd_size_addr = 0,
.last_child_rd_addr = get_last_rd_offset(),
.last_child_rd_size_addr = get_last_rd_size(),
.last_child_success = get_last_success() };
};

// Input / Output
std::vector<FF> get_calldata(uint32_t cd_offset, uint32_t cd_size) const override
{
// TODO(ilyas): Do we assert to assert cd_size < calldata.size(), otherwise it could trigger a massive write of
// zeroes. OTOH: this should be caught by an OUT_OF_GAS exception
std::vector<FF> padded_calldata(cd_size, 0); // Vector of size cd_size filled with zeroes;

// We first take a slice of the data, the most we can slice is the actual size of the data
size_t slice_size = std::min(static_cast<size_t>(cd_offset + cd_size), calldata.size());

for (size_t i = cd_offset; i < slice_size; i++) {
padded_calldata[i] = calldata[i];
}
return padded_calldata;
};

private:
std::vector<FF> calldata;
};

// Parameters for a nested call need to be changed
Expand All @@ -150,20 +202,52 @@ class NestedContext : public BaseContext {
NestedContext(uint32_t context_id,
AztecAddress address,
AztecAddress msg_sender,
std::span<const FF> calldata,
bool is_static,
std::unique_ptr<BytecodeManagerInterface> bytecode,
std::unique_ptr<MemoryInterface> memory,
EventEmitterInterface<ContextStackEvent>& ctx_stack_events)
: BaseContext(context_id,
address,
msg_sender,
calldata,
is_static,
std::move(bytecode),
std::move(memory),
ctx_stack_events)
ContextInterface& parent_context,
MemoryAddress cd_offset_address, /* This is a direct mem address */
MemoryAddress cd_size_address /* This is a direct mem address */
)
: BaseContext(context_id, address, msg_sender, is_static, std::move(bytecode), std::move(memory))
, parent_cd_offset(cd_offset_address)
, parent_cd_size(cd_size_address)
, parent_context(parent_context)
{}

// Event Emitting
ContextEvent serialize_context_event() override
{
return { .id = get_context_id(),
.pc = get_pc(),
.msg_sender = get_msg_sender(),
.contract_addr = get_address(),
.is_static = get_is_static(),
.parent_cd_addr = parent_cd_offset,
.parent_cd_size_addr = parent_cd_size };
};

// Input / Output
std::vector<FF> get_calldata(uint32_t cd_offset, uint32_t cd_size) const override
{
ValueRefAndTag get_calldata_size = parent_context.get_memory().get(parent_cd_size);
// TODO(ilyas): error if tag != U32
auto calldata_size = static_cast<uint32_t>(get_calldata_size.value);
uint32_t read_size = std::min(cd_offset + cd_size, calldata_size);

auto retrieved_calldata = parent_context.get_memory().get_slice(parent_cd_offset + cd_offset, read_size).first;

// Pad the calldata
retrieved_calldata.resize(cd_size, 0);
return retrieved_calldata;
};

private:
// These are direct addresses to look up into the parent context during calldata copying
MemoryAddress parent_cd_offset;
MemoryAddress parent_cd_size;

ContextInterface& parent_context;
};

} // namespace bb::avm2::simulation
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,15 @@ struct ContextEvent {
AztecAddress contract_addr;
bool is_static;

// Calldata info
// uint32_t cd_addr;
// uint32_t cd_size_addr;

// Returndata info
// uint32_t rd_addr;
// uint32_t rd_size_addr;
// Calldata info from parent context
uint32_t parent_cd_addr;
uint32_t parent_cd_size_addr;

// Returndata info from child context
uint32_t last_child_rd_addr;
uint32_t last_child_rd_size_addr;
// Success
// bool nested_ctx_success;
bool last_child_success;

// Gas
// uint32_t l2_gas_used;
Expand All @@ -47,9 +46,9 @@ struct ContextStackEvent {
AztecAddress contract_addr;
bool is_static;

// Calldata info
// uint32_t cd_addr;
// uint32_t cd_size_addr;
// Calldata info from parent context
uint32_t parent_cd_addr;
uint32_t parent_cd_size_addr;

// Gas
// uint32_t l2_gas_used;
Expand Down
Loading