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
72 changes: 70 additions & 2 deletions barretenberg/cpp/pil/vm2/context.pil
Original file line number Diff line number Diff line change
@@ -1,17 +1,85 @@
// This is a virtual gadget, which is part of the execution trace.
namespace execution;

// This the same sel as in execution
#[skippable_if]
sel = 0;

// Useful to define some opcodes within this pil file
// Constrained to be boolean by execution instruction spec table
pol commit sel_call;
pol commit sel_static_call;
pol CALL = sel_call + sel_static_call; // Guaranteed to be mutually exclusive
// CALL & precomputed.first_row are NAND
CALL * precomputed.first_row = 0;

// Context columns
pol commit context_id;
pol commit parent_id;
pol commit pc;
pol commit next_pc;
pol commit msg_sender;
pol commit contract_address;

// Constrained boolean by tx trace (for enqueued call) and #[NEXT_IS_STATIC] for nested
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...

// ==== Helper columns ====
// TODO: These context modifiers also need to factor in when a new enqueued call occurs
// REPLACE prefixed precomputed.first_row in relations with actual phase / enqueued call change
pol NOT_FIRST = (1 - precomputed.first_row); // Temp

// next_context_id increments with each invocation of an external call or new enqueued call
pol commit next_context_id; // Can be replaced by clk
// The initial next_context_id = 2, in row = 1
#[INCR_CONTEXT_ID]
NOT_FIRST * sel' * (next_context_id' - (next_context_id + CALL)) = 0;

// CALL = 1 <==> context_id' = next_context_id
// CALL = 0 <==> context_id' = context_id
#[NEXT_CONTEXT_ID]
NOT_FIRST * sel' * ((next_context_id - context_id) * CALL + context_id + precomputed.first_row - context_id') = 0;

// CALL = 1 <==> parent_id' = context_id
// CALL = 0 <==> parent_id' = parent_id
#[NEXT_PARENT_ID]
NOT_FIRST * sel' * ((context_id - parent_id) * (CALL + precomputed.first_row) + parent_id - parent_id') = 0;

// CALL = 1 <==> pc' = 0
// CALL = 0 <==> pc' = next_pc
#[NEXT_PC]
NOT_FIRST * sel' * (pc' - ((1 - CALL) * next_pc)) = 0;

// CALL = 1 <==> msg_sender' = contract_address
// CALL = 0 <==> msg_sender' = msg_sender
#[NEXT_MSG_SENDER]
NOT_FIRST * sel' * ((contract_address - msg_sender) * CALL + msg_sender - msg_sender') = 0;

// CALL = 1 <==> contract_address' = reg3 (intermediate register 3 from execution trace)
// CALL = 0 <==> contract_address' = contract_address
#[NEXT_CONTRACT_ADDR]
NOT_FIRST * sel' * ((reg3 - contract_address) * CALL + contract_address - contract_address') = 0;

// CALL = 1 && static_call = 1 <==> is_static' = 1
// CALL = 1 && static_call = 0 <==> is_static' = 0
// CALL = 0 && static_call = 0 <==> is_static' = is_static
#[NEXT_IS_STATIC]
NOT_FIRST * sel' * (is_static' - (sel_static_call + (1 - CALL) * is_static)) = 0;

// CALL = 1 <==> parent_calldata_offset_addr' = rop4 (resolved operand 4 from execution trace)
// CALL = 0 <==> parent_calldata_offset_addr' = parent_calldata_offset_addr
#[NEXT_CD_OFFSET]
NOT_FIRST * sel' * ((rop4 - parent_calldata_offset_addr) * CALL + parent_calldata_offset_addr - parent_calldata_offset_addr') = 0;

// CALL = 1 <==> parent_calldata_size_addr' = rop5 (resolved operand 5 from execution trace)
// CALL = 0 <==> parent_calldata_size_addr' = parent_calldata_size_addr
#[NEXT_CD_SIZE]
NOT_FIRST * sel' * ((rop5 - parent_calldata_size_addr) * CALL + parent_calldata_size_addr - parent_calldata_size_addr') = 0;


5 changes: 2 additions & 3 deletions barretenberg/cpp/pil/vm2/context_stack.pil
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
namespace context_stack;

pol commit context_id;
pol commit pc;
pol commit parent_id;
pol commit next_pc;
pol commit msg_sender;
pol commit contract_address;

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

pol commit parent_calldata_offset_addr;
pol commit parent_calldata_size_addr;
4 changes: 4 additions & 0 deletions barretenberg/cpp/pil/vm2/execution.pil
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ include "nullifier_check.pil";
namespace execution;

pol commit sel; // subtrace selector

#[skippable_if]
Copy link
Contributor

Choose a reason for hiding this comment

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

ohh we didn't have this

sel = 0;

// Subtrace operation id
pol commit subtrace_operation_id;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ using tracegen::TestTraceContainer;
using FF = AvmFlavorSettings::FF;
using C = Column;
using execution = bb::avm2::execution<FF>;
using context = bb::avm2::context<FF>;

TEST(ExecutionConstrainingTest, Basic)
{
Expand Down Expand Up @@ -43,6 +44,50 @@ TEST(ExecutionConstrainingTest, Continuity)
check_relation<execution>(trace, execution::SR_TRACE_CONTINUITY_1, execution::SR_TRACE_CONTINUITY_2);
}

TEST(ExecutionConstrainingTest, ContextSwitchingCall)
{
TestTraceContainer trace({ {
{ C::execution_next_context_id, 0 },
{ C::precomputed_first_row, 1 },
},
// Dummy Row
{ { C::execution_sel, 1 },
{ C::execution_pc, 0 },
{ C::execution_next_pc, 1 },
{ C::execution_context_id, 1 },
{ C::execution_next_context_id, 2 } },
// CALL
{
{ C::execution_sel, 1 },
{ C::execution_pc, 1 },
{ C::execution_next_pc, 2 },
{ C::execution_sel_call, 1 },
{ C::execution_context_id, 1 },
{ C::execution_next_context_id, 2 },
{ C::execution_rop4, /*cd offset=*/10 },
{ C::execution_rop5, /*cd size=*/1 },
{ C::execution_reg3, /*contract address=*/0xdeadbeef },
},
// Dummy Row in new context
{
{ C::execution_sel, 1 },
{ C::execution_pc, 0 }, // pc=0 because it is after a CALL
{ C::execution_next_pc, 20 },
{ C::execution_context_id, 2 }, // Previous row next_context_id
{ C::execution_next_context_id, 3 }, // Incremented due to previous call
{ C::execution_parent_id, 1 }, // Previous row context id
{ C::execution_contract_address, 0xdeadbeef },
{ C::execution_parent_calldata_offset_addr, 10 },
{ C::execution_parent_calldata_size_addr, 1 },
},
{
{ C::execution_sel, 0 },
{ C::execution_last, 1 },
} });

check_relation<context>(trace);
}

TEST(ExecutionConstrainingTest, ContinuityBrokenFirstRow)
{
// clang-format off
Expand Down
10 changes: 5 additions & 5 deletions barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "relations/bitwise.hpp"
#include "relations/class_id_derivation.hpp"
#include "relations/context.hpp"
#include "relations/context_stack.hpp"
#include "relations/ecc.hpp"
#include "relations/execution.hpp"
#include "relations/ff_gt.hpp"
Expand Down Expand Up @@ -51,10 +50,10 @@ namespace bb::avm2 {

struct AvmFlavorVariables {
static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 70;
static constexpr size_t NUM_WITNESS_ENTITIES = 2071;
static constexpr size_t NUM_SHIFTED_ENTITIES = 135;
static constexpr size_t NUM_WITNESS_ENTITIES = 2077;
static constexpr size_t NUM_SHIFTED_ENTITIES = 144;
static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES;
static constexpr size_t NUM_ALL_ENTITIES = 2276;
static constexpr size_t NUM_ALL_ENTITIES = 2291;

// Need to be templated for recursive verifier
template <typename FF_>
Expand All @@ -68,7 +67,6 @@ struct AvmFlavorVariables {
avm2::bitwise<FF_>,
avm2::class_id_derivation<FF_>,
avm2::context<FF_>,
avm2::context_stack<FF_>,
avm2::ecc<FF_>,
avm2::execution<FF_>,
avm2::ff_gt<FF_>,
Expand Down
122 changes: 119 additions & 3 deletions barretenberg/cpp/src/barretenberg/vm2/generated/relations/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,107 @@ template <typename FF_> class contextImpl {
public:
using FF = FF_;

static constexpr std::array<size_t, 1> SUBRELATION_PARTIAL_LENGTHS = { 3 };
static constexpr std::array<size_t, 10> SUBRELATION_PARTIAL_LENGTHS = { 3, 4, 5, 5, 5, 5, 5, 5, 5, 5 };

template <typename AllEntities> inline static bool skip(const AllEntities& in)
{
const auto& new_term = in;
return (new_term.execution_sel).is_zero();
}

template <typename ContainerOverSubrelations, typename AllEntities>
void static accumulate(ContainerOverSubrelations& evals,
const AllEntities& new_term,
[[maybe_unused]] const RelationParameters<FF>&,
[[maybe_unused]] const FF& scaling_factor)
{
const auto execution_CALL = new_term.execution_sel_call + new_term.execution_sel_static_call;
const auto execution_NOT_FIRST = (FF(1) - new_term.precomputed_first_row);

{
using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>;
auto tmp = new_term.execution_is_static * (FF(1) - new_term.execution_is_static);
auto tmp = execution_CALL * new_term.precomputed_first_row;
tmp *= scaling_factor;
std::get<0>(evals) += typename Accumulator::View(tmp);
}
{ // INCR_CONTEXT_ID
using Accumulator = typename std::tuple_element_t<1, ContainerOverSubrelations>;
auto tmp =
execution_NOT_FIRST * new_term.execution_sel_shift *
(new_term.execution_next_context_id_shift - (new_term.execution_next_context_id + execution_CALL));
tmp *= scaling_factor;
std::get<1>(evals) += typename Accumulator::View(tmp);
}
{ // NEXT_CONTEXT_ID
using Accumulator = typename std::tuple_element_t<2, ContainerOverSubrelations>;
auto tmp = execution_NOT_FIRST * new_term.execution_sel_shift *
(((new_term.execution_next_context_id - new_term.execution_context_id) * execution_CALL +
new_term.execution_context_id + new_term.precomputed_first_row) -
new_term.execution_context_id_shift);
tmp *= scaling_factor;
std::get<2>(evals) += typename Accumulator::View(tmp);
}
{ // NEXT_PARENT_ID
using Accumulator = typename std::tuple_element_t<3, ContainerOverSubrelations>;
auto tmp = execution_NOT_FIRST * new_term.execution_sel_shift *
(((new_term.execution_context_id - new_term.execution_parent_id) *
(execution_CALL + new_term.precomputed_first_row) +
new_term.execution_parent_id) -
new_term.execution_parent_id_shift);
tmp *= scaling_factor;
std::get<3>(evals) += typename Accumulator::View(tmp);
}
{ // NEXT_PC
using Accumulator = typename std::tuple_element_t<4, ContainerOverSubrelations>;
auto tmp = execution_NOT_FIRST * new_term.execution_sel_shift *
(new_term.execution_pc_shift - (FF(1) - execution_CALL) * new_term.execution_next_pc);
tmp *= scaling_factor;
std::get<4>(evals) += typename Accumulator::View(tmp);
}
{ // NEXT_MSG_SENDER
using Accumulator = typename std::tuple_element_t<5, ContainerOverSubrelations>;
auto tmp = execution_NOT_FIRST * new_term.execution_sel_shift *
(((new_term.execution_contract_address - new_term.execution_msg_sender) * execution_CALL +
new_term.execution_msg_sender) -
new_term.execution_msg_sender_shift);
tmp *= scaling_factor;
std::get<5>(evals) += typename Accumulator::View(tmp);
}
{ // NEXT_CONTRACT_ADDR
using Accumulator = typename std::tuple_element_t<6, ContainerOverSubrelations>;
auto tmp = execution_NOT_FIRST * new_term.execution_sel_shift *
(((new_term.execution_reg3 - new_term.execution_contract_address) * execution_CALL +
new_term.execution_contract_address) -
new_term.execution_contract_address_shift);
tmp *= scaling_factor;
std::get<6>(evals) += typename Accumulator::View(tmp);
}
{ // NEXT_IS_STATIC
using Accumulator = typename std::tuple_element_t<7, ContainerOverSubrelations>;
auto tmp = execution_NOT_FIRST * new_term.execution_sel_shift *
(new_term.execution_is_static_shift -
(new_term.execution_sel_static_call + (FF(1) - execution_CALL) * new_term.execution_is_static));
tmp *= scaling_factor;
std::get<7>(evals) += typename Accumulator::View(tmp);
}
{ // NEXT_CD_OFFSET
using Accumulator = typename std::tuple_element_t<8, ContainerOverSubrelations>;
auto tmp = execution_NOT_FIRST * new_term.execution_sel_shift *
(((new_term.execution_rop4 - new_term.execution_parent_calldata_offset_addr) * execution_CALL +
new_term.execution_parent_calldata_offset_addr) -
new_term.execution_parent_calldata_offset_addr_shift);
tmp *= scaling_factor;
std::get<8>(evals) += typename Accumulator::View(tmp);
}
{ // NEXT_CD_SIZE
using Accumulator = typename std::tuple_element_t<9, ContainerOverSubrelations>;
auto tmp = execution_NOT_FIRST * new_term.execution_sel_shift *
(((new_term.execution_rop5 - new_term.execution_parent_calldata_size_addr) * execution_CALL +
new_term.execution_parent_calldata_size_addr) -
new_term.execution_parent_calldata_size_addr_shift);
tmp *= scaling_factor;
std::get<9>(evals) += typename Accumulator::View(tmp);
}
}
};

Expand All @@ -36,9 +122,39 @@ template <typename FF> class context : public Relation<contextImpl<FF>> {

static std::string get_subrelation_label(size_t index)
{
switch (index) {}
switch (index) {
case 1:
return "INCR_CONTEXT_ID";
case 2:
return "NEXT_CONTEXT_ID";
case 3:
return "NEXT_PARENT_ID";
case 4:
return "NEXT_PC";
case 5:
return "NEXT_MSG_SENDER";
case 6:
return "NEXT_CONTRACT_ADDR";
case 7:
return "NEXT_IS_STATIC";
case 8:
return "NEXT_CD_OFFSET";
case 9:
return "NEXT_CD_SIZE";
}
return std::to_string(index);
}

// Subrelation indices constants, to be used in tests.
static constexpr size_t SR_INCR_CONTEXT_ID = 1;
static constexpr size_t SR_NEXT_CONTEXT_ID = 2;
static constexpr size_t SR_NEXT_PARENT_ID = 3;
static constexpr size_t SR_NEXT_PC = 4;
static constexpr size_t SR_NEXT_MSG_SENDER = 5;
static constexpr size_t SR_NEXT_CONTRACT_ADDR = 6;
static constexpr size_t SR_NEXT_IS_STATIC = 7;
static constexpr size_t SR_NEXT_CD_OFFSET = 8;
static constexpr size_t SR_NEXT_CD_SIZE = 9;
};

} // namespace bb::avm2

This file was deleted.

Loading