Skip to content

Commit

Permalink
feat(avm): e2e send l1 msg (#6880)
Browse files Browse the repository at this point in the history
End to end from ts -> avm prove + verify for emit l2 to l1 msg
  • Loading branch information
Maddiaa0 authored Jun 5, 2024
1 parent 9f5b113 commit deb972d
Show file tree
Hide file tree
Showing 10 changed files with 60 additions and 72 deletions.
2 changes: 1 addition & 1 deletion barretenberg/cpp/pil/avm/avm_kernel.pil
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ namespace avm_kernel(256);
pol START_SLOAD_WRITE_OFFSET = 144; // START_SSTORE_WRITE_OFFSET + MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL

// Emit data
pol START_EMIT_NOTE_HASH_WRITE_OFFSET = 160; // START_SSTORE_WRITE_OFFSET + MAX_PUBLIC_DATA_READS_PER_CALL
pol START_EMIT_NOTE_HASH_WRITE_OFFSET = 160; // START_SLOAD_WRITE_OFFSET + MAX_PUBLIC_DATA_READS_PER_CALL
pol START_EMIT_NULLIFIER_WRITE_OFFSET = 176; // START_EMIT_NOTE_HASH_WRITE_OFFSET + MAX_NEW_NOTE_HASHES_PER_CALL
pol START_EMIT_L2_TO_l1_MSG = 192; // START_EMIT_NULLIFIER_WRITE_OFFSET + MAX_NEW_NULLIFIERS_PER_CALL
pol START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET = 194; // START_EMIT_L2_TO_L1_MSG + MAX_NEW_L2_TO_L1_MSGS_PER_CALL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const std::unordered_map<OpCode, std::vector<OperandType>> OPCODE_WIRE_FORMAT =
{ OpCode::EMITNOTEHASH, getter_format }, // TODO: new format for these
{ OpCode::EMITNULLIFIER, getter_format }, // TODO: new format for these
{ OpCode::EMITUNENCRYPTEDLOG, getter_format },
{ OpCode::SENDL2TOL1MSG, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } },
{ OpCode::SLOAD, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } },
{ OpCode::SSTORE, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } },
/*TODO: leafIndexOffset is not constrained*/
Expand Down
15 changes: 8 additions & 7 deletions barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,7 @@ VmPublicInputs Execution::convert_public_inputs(std::vector<FF> const& public_in

ko_values[dest_offset] = public_inputs_vec[pcpi_offset];
ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1];
// TEMP: hardcode written non existent to 1
// ko_metadata[dest_offset] = FF(1);
ko_metadata[dest_offset] = FF(1);
}
// For NULLIFIEREXISTS - non existent
for (size_t i = 0; i < MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL; i++) {
Expand All @@ -174,8 +173,7 @@ VmPublicInputs Execution::convert_public_inputs(std::vector<FF> const& public_in

ko_values[dest_offset] = public_inputs_vec[pcpi_offset];
ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1];
// TEMP: hardcode written non_existent to 0
// ko_metadata[dest_offset] = FF(0);
ko_metadata[dest_offset] = FF(0);
}
// For L1TOL2MSGEXISTS
for (size_t i = 0; i < MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL; i++) {
Expand Down Expand Up @@ -227,8 +225,10 @@ VmPublicInputs Execution::convert_public_inputs(std::vector<FF> const& public_in
size_t dest_offset = AvmKernelTraceBuilder::START_L2_TO_L1_MSG_WRITE_OFFSET + i;
size_t pcpi_offset = PCPI_NEW_L2_TO_L1_MSGS_OFFSET + (i * L2_TO_L1_MESSAGE_LENGTH);

ko_values[dest_offset] = public_inputs_vec[pcpi_offset];
ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1];
// Note: unorthadox order
ko_metadata[dest_offset] = public_inputs_vec[pcpi_offset];
ko_values[dest_offset] = public_inputs_vec[pcpi_offset + 1];
ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 2];
}
// For EMITUNENCRYPTEDLOG
for (size_t i = 0; i < MAX_UNENCRYPTED_LOGS_PER_CALL; i++) {
Expand Down Expand Up @@ -505,7 +505,8 @@ std::vector<Row> Execution::gen_trace(std::vector<Instruction> const& instructio
trace_builder.op_emit_unencrypted_log(std::get<uint32_t>(inst.operands.at(1)));
break;
case OpCode::SENDL2TOL1MSG:
trace_builder.op_emit_l2_to_l1_msg(std::get<uint32_t>(inst.operands.at(1)));
trace_builder.op_emit_l2_to_l1_msg(std::get<uint32_t>(inst.operands.at(1)),
std::get<uint32_t>(inst.operands.at(2)));
break;
// Machine State - Internal Control Flow
case OpCode::JUMP:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ void AvmKernelTraceBuilder::op_nullifier_exists(uint32_t clk,
const FF& nullifier,
uint32_t result)
{
info("nullifier exists result ", result);
uint32_t offset = 0;
if (result == 1) {
offset = START_NULLIFIER_EXISTS_OFFSET + nullifier_exists_offset;
Expand All @@ -155,7 +154,6 @@ void AvmKernelTraceBuilder::op_nullifier_exists(uint32_t clk,
offset = START_NULLIFIER_NON_EXISTS_OFFSET + nullifier_non_exists_offset;
nullifier_non_exists_offset++;
}
info("nullifier exists offset ", offset);
perform_kernel_output_lookup(offset, side_effect_counter, nullifier, FF(result));

KernelTraceEntry entry = {
Expand Down Expand Up @@ -217,10 +215,13 @@ void AvmKernelTraceBuilder::op_emit_unencrypted_log(uint32_t clk, uint32_t side_
kernel_trace.push_back(entry);
}

void AvmKernelTraceBuilder::op_emit_l2_to_l1_msg(uint32_t clk, uint32_t side_effect_counter, const FF& l2_to_l1_msg)
void AvmKernelTraceBuilder::op_emit_l2_to_l1_msg(uint32_t clk,
uint32_t side_effect_counter,
const FF& l2_to_l1_msg,
const FF& recipient)
{
uint32_t offset = START_L2_TO_L1_MSG_WRITE_OFFSET + emit_l2_to_l1_msg_offset;
perform_kernel_output_lookup(offset, side_effect_counter, l2_to_l1_msg, FF(0));
perform_kernel_output_lookup(offset, side_effect_counter, l2_to_l1_msg, recipient);
emit_l2_to_l1_msg_offset++;

KernelTraceEntry entry = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class AvmKernelTraceBuilder {
void op_emit_nullifier(uint32_t clk, uint32_t side_effect_counter, const FF& nullifier);
void op_l1_to_l2_msg_exists(uint32_t clk, uint32_t side_effect_counter, const FF& message, uint32_t result);
void op_emit_unencrypted_log(uint32_t clk, uint32_t side_effect_counter, const FF& log_hash);
void op_emit_l2_to_l1_msg(uint32_t clk, uint32_t side_effect_counter, const FF& message);
void op_emit_l2_to_l1_msg(uint32_t clk, uint32_t side_effect_counter, const FF& message, const FF& recipient);

void op_sload(uint32_t clk, uint32_t side_effect_counter, const FF& slot, const FF& value);
void op_sstore(uint32_t clk, uint32_t side_effect_counter, const FF& slot, const FF& value);
Expand Down
48 changes: 6 additions & 42 deletions barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1352,34 +1352,6 @@ Row AvmTraceBuilder::create_kernel_output_opcode_with_metadata(
};
}

// TODO: fix the naming here - we need it to be different as we are writing a hint
// Row AvmTraceBuilder::create_sload(
// uint32_t clk, uint32_t data_offset, FF const& data_value, FF const& slot_value, uint32_t slot_offset)
// {
// // We write the sload into memory, where the sload is an injected value that is mapped to the public inputs
// mem_trace_builder.write_into_memory(
// call_ptr, clk, IntermRegister::IA, data_offset, data_value, AvmMemoryTag::FF, AvmMemoryTag::FF);

// return Row{
// .avm_main_clk = clk,
// .avm_main_ia = data_value,
// .avm_main_ib = slot_value,
// .avm_main_ind_a = 0,
// .avm_main_ind_b = 0,
// .avm_main_internal_return_ptr = internal_return_ptr,
// .avm_main_mem_idx_a = data_offset,
// .avm_main_mem_idx_b = slot_offset,
// .avm_main_mem_op_a = 1,
// .avm_main_mem_op_b = 1,
// .avm_main_pc = pc++,
// .avm_main_q_kernel_output_lookup = 1,
// .avm_main_r_in_tag = static_cast<uint32_t>(AvmMemoryTag::FF),
// .avm_main_rwa = 1,
// .avm_main_rwb = 0,
// .avm_main_w_in_tag = static_cast<uint32_t>(AvmMemoryTag::FF),
// };
// }

Row AvmTraceBuilder::create_kernel_output_opcode_with_set_metadata_output_from_hint(uint32_t clk,
uint32_t data_offset,
uint32_t metadata_offset)
Expand Down Expand Up @@ -1476,12 +1448,14 @@ void AvmTraceBuilder::op_emit_nullifier(uint32_t nullifier_offset)
side_effect_counter++;
}

void AvmTraceBuilder::op_emit_l2_to_l1_msg(uint32_t msg_offset)
void AvmTraceBuilder::op_emit_l2_to_l1_msg(uint32_t recipient_offset, uint32_t msg_offset)
{
auto const clk = static_cast<uint32_t>(main_trace.size()) + 1;

Row row = create_kernel_output_opcode(clk, msg_offset);
kernel_trace_builder.op_emit_l2_to_l1_msg(clk, side_effect_counter, row.avm_main_ia);
// Note: unorthadox order - as seen in L2ToL1Message struct in TS
Row row = create_kernel_output_opcode_with_metadata(
clk, msg_offset, AvmMemoryTag::FF, recipient_offset, AvmMemoryTag::FF);
kernel_trace_builder.op_emit_l2_to_l1_msg(clk, side_effect_counter, row.avm_main_ia, row.avm_main_ib);
row.avm_main_sel_op_emit_l2_to_l1_msg = FF(1);

// Constrain gas cost
Expand Down Expand Up @@ -1530,7 +1504,7 @@ void AvmTraceBuilder::op_note_hash_exists(uint32_t note_offset, uint32_t dest_of
Row row = create_kernel_output_opcode_with_set_metadata_output_from_hint(clk, note_offset, dest_offset);
kernel_trace_builder.op_note_hash_exists(
clk, side_effect_counter, row.avm_main_ia, /*safe*/ static_cast<uint32_t>(row.avm_main_ib));
row.avm_main_sel_op_l1_to_l2_msg_exists = FF(1);
row.avm_main_sel_op_note_hash_exists = FF(1);

// Constrain gas cost
gas_trace_builder.constrain_gas_lookup(clk, OpCode::NOTEHASHEXISTS);
Expand Down Expand Up @@ -4012,18 +3986,8 @@ std::vector<Row> AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c

// The side effect counter will increment regardless of the offset value
next.avm_kernel_side_effect_counter = curr.avm_kernel_side_effect_counter + 1;

info("non exists curr: ", curr.avm_kernel_nullifier_non_exists_write_offset);
info("non exists next: ", next.avm_kernel_nullifier_non_exists_write_offset);
}

info("for kernel output", curr.avm_main_sel_op_nullifier_exists);
info(curr.avm_main_sel_op_nullifier_exists *
(curr.avm_kernel_kernel_out_offset -
((curr.avm_main_ib * (FF(32) + curr.avm_kernel_nullifier_exists_write_offset)) +
((FF(1) - curr.avm_main_ib) * (FF(64) + curr.avm_kernel_nullifier_non_exists_write_offset)))));
info("kernel out offset:", curr.avm_kernel_kernel_out_offset);

kernel_padding_main_trace_bottom = clk + 1;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class AvmTraceBuilder {
void op_emit_note_hash(uint32_t note_hash_offset);
void op_emit_nullifier(uint32_t nullifier_offset);
void op_emit_unencrypted_log(uint32_t log_offset);
void op_emit_l2_to_l1_msg(uint32_t msg_offset);
void op_emit_l2_to_l1_msg(uint32_t msg_offset, uint32_t recipient_offset);
void op_get_contract_instance(uint8_t indirect, uint32_t address_offset, uint32_t dst_offset);

// With additional metadata output
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1662,6 +1662,10 @@ TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes)
+ to_hex(OpCode::EMITUNENCRYPTEDLOG) + // opcode EMITNOTEHASH
"00" // Indirect flag
"00000001" // src offset 1
+ to_hex(OpCode::SENDL2TOL1MSG) + // opcode EMITNOTEHASH
"00" // Indirect flag
"00000001" // src offset 1
"00000001" // src offset 1
+ to_hex(OpCode::RETURN) + // opcode RETURN
"00" // Indirect flag
"00000000" // ret offset 0
Expand All @@ -1670,7 +1674,7 @@ TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes)
auto bytecode = hex_to_bytes(bytecode_hex);
auto instructions = Deserialization::parse(bytecode);

ASSERT_THAT(instructions, SizeIs(6));
ASSERT_THAT(instructions, SizeIs(7));

std::vector<FF> calldata = {};
std::vector<FF> returndata = {};
Expand Down Expand Up @@ -1714,6 +1718,20 @@ TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes)
EXPECT_EQ(emit_log_kernel_out_row->avm_kernel_kernel_value_out__is_public, 1);
EXPECT_EQ(emit_log_kernel_out_row->avm_kernel_kernel_side_effect_out__is_public, 2);

// CHECK SEND L2 TO L1 MSG
auto send_row = std::ranges::find_if(
trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_emit_l2_to_l1_msg == 1; });
EXPECT_EQ(send_row->avm_main_ia, 1);
EXPECT_EQ(send_row->avm_main_ib, 1);
EXPECT_EQ(send_row->avm_kernel_side_effect_counter, 3);

auto msg_out_row = std::ranges::find_if(trace.begin(), trace.end(), [&](Row r) {
return r.avm_main_clk == AvmKernelTraceBuilder::START_L2_TO_L1_MSG_WRITE_OFFSET;
});
EXPECT_EQ(msg_out_row->avm_kernel_kernel_value_out__is_public, 1);
EXPECT_EQ(msg_out_row->avm_kernel_kernel_side_effect_out__is_public, 3);
EXPECT_EQ(msg_out_row->avm_kernel_kernel_metadata_out__is_public, 1);

validate_trace(std::move(trace));
}

Expand Down
18 changes: 10 additions & 8 deletions barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,10 +708,12 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitNullifier)

TEST_F(AvmKernelOutputPositiveTests, kernelEmitL2ToL1Msg)
{
uint32_t offset = 42;
uint32_t msg_offset = 42;
uint32_t recipient_offset = 69;
auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) {
trace_builder.op_set(0, 1234, offset, AvmMemoryTag::FF);
trace_builder.op_emit_l2_to_l1_msg(offset);
trace_builder.op_set(0, 1234, msg_offset, AvmMemoryTag::FF);
trace_builder.op_set(0, 420, recipient_offset, AvmMemoryTag::FF);
trace_builder.op_emit_l2_to_l1_msg(recipient_offset, msg_offset);
};
auto checks = [=](const std::vector<Row>& trace) {
std::vector<Row>::const_iterator row = std::ranges::find_if(
Expand All @@ -721,17 +723,19 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitL2ToL1Msg)
// Check the outputs of the trace
uint32_t output_offset = AvmKernelTraceBuilder::START_L2_TO_L1_MSG_WRITE_OFFSET;

expect_output_table_row(
expect_output_table_row_with_metadata(
row,
/*kernel_in_offset=*/output_offset,
/*ia=*/1234, // Note the value generated above for public inputs is the same as the index read + 1
/*mem_idx_a=*/offset,
/*mem_idx_a=*/msg_offset,
/*ib=*/420,
/*mem_idx_b=*/recipient_offset,
/*w_in_tag=*/AvmMemoryTag::FF,
/*side_effect_counter=*/0

);

check_kernel_outputs(trace.at(output_offset), 1234, /*side_effect_counter=*/0, /*metadata=*/0);
check_kernel_outputs(trace.at(output_offset), 1234, /*side_effect_counter=*/0, /*metadata=*/420);
};

test_kernel_lookup(apply_opcodes, checks);
Expand Down Expand Up @@ -948,8 +952,6 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNullifierNonExists)
/*w_in_tag=*/AvmMemoryTag::FF,
/*side_effect_counter=*/0);

log_avm_trace(trace, 2, 4);

check_kernel_outputs(trace.at(output_offset), value, /*side_effect_counter=*/0, exists);
};

Expand Down
15 changes: 8 additions & 7 deletions yarn-project/bb-prover/src/avm_proving.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,20 +110,21 @@ describe('AVM WitGen, proof generation and verification', () => {
TIMEOUT,
);

it(
'Should prove send l2 to l1 msg',
async () => {
await proveAndVerifyAvmTestContract('send_l2_to_l1_msg', [new Fr(1), new Fr(2)]);
},
TIMEOUT,
);

// TODO: requires revert
// it("Should prove to radix",
// async () => {
// await proveAndVerifyAvmTestContract('to_radix_le', [new Fr(10)]);
// },
// TIMEOUT
// )

// it("Should prove send l2 to l1 msg",
// async () => {
// await proveAndVerifyAvmTestContract('send_l2_to_l1_msg', [new Fr(1), new Fr(2)]);
// },
// TIMEOUT
// )
});

const proveAndVerifyAvmTestContract = async (functionName: string, calldata: Fr[] = []) => {
Expand Down

0 comments on commit deb972d

Please sign in to comment.