Skip to content

Commit

Permalink
7211: calldata passed through the verifier
Browse files Browse the repository at this point in the history
  • Loading branch information
jeanmon committed Jun 28, 2024
1 parent 81f804e commit 2e86e25
Show file tree
Hide file tree
Showing 19 changed files with 214 additions and 106 deletions.
11 changes: 8 additions & 3 deletions barretenberg/cpp/src/barretenberg/bb/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,18 +723,22 @@ void avm_prove(const std::filesystem::path& bytecode_path,
*
* @param proof_path Path to the file containing the serialized proof
* @param vk_path Path to the file containing the serialized verification key
* @param calldata_path Path to the file containing the serialised calldata (could be empty)
* @return true If the proof is valid
* @return false If the proof is invalid
*/
bool avm_verify(const std::filesystem::path& proof_path, const std::filesystem::path& vk_path)
bool avm_verify(const std::filesystem::path& proof_path,
const std::filesystem::path& vk_path,
const std::filesystem::path& calldata_path)
{
std::vector<fr> const proof = many_from_buffer<fr>(read_file(proof_path));
std::vector<fr> const calldata = many_from_buffer<fr>(read_file(calldata_path));
std::vector<uint8_t> vk_bytes = read_file(vk_path);
auto circuit_size = from_buffer<size_t>(vk_bytes, 0);
auto num_public_inputs = from_buffer<size_t>(vk_bytes, sizeof(size_t));
auto vk = AvmFlavor::VerificationKey(circuit_size, num_public_inputs);

const bool verified = avm_trace::Execution::verify(vk, proof);
const bool verified = avm_trace::Execution::verify(vk, proof, calldata);
vinfo("verified: ", verified);
return verified;
}
Expand Down Expand Up @@ -1144,7 +1148,8 @@ int main(int argc, char* argv[])
avm_dump_trace_path = get_option(args, "--avm-dump-trace", "");
avm_prove(avm_bytecode_path, avm_calldata_path, avm_public_inputs_path, avm_hints_path, output_path);
} else if (command == "avm_verify") {
return avm_verify(proof_path, vk_path) ? 0 : 1;
std::filesystem::path avm_calldata_path = get_option(args, "--avm-calldata", "./target/avm_calldata.bin");
return avm_verify(proof_path, vk_path, avm_calldata_path) ? 0 : 1;
#endif
} else if (command == "prove_ultra_honk") {
std::string output_path = get_option(args, "-o", "./proofs/proof");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ VmPublicInputs Execution::convert_public_inputs(std::vector<FF> const& public_in
return public_inputs;
}

bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof)
bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof, std::vector<FF> const& calldata)
{
auto verification_key = std::make_shared<AvmFlavor::VerificationKey>(vk);
AvmVerifier verifier(verification_key);
Expand All @@ -268,7 +268,7 @@ bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof)
std::copy(proof.begin() + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, proof.end(), std::back_inserter(raw_proof));

VmPublicInputs public_inputs = convert_public_inputs(public_inputs_vec);
std::vector<std::vector<FF>> public_inputs_columns = copy_public_inputs_columns(public_inputs);
std::vector<std::vector<FF>> public_inputs_columns = copy_public_inputs_columns(public_inputs, calldata);
return verifier.verify_proof(raw_proof, public_inputs_columns);
}

Expand Down Expand Up @@ -309,7 +309,7 @@ std::vector<Row> Execution::gen_trace(std::vector<Instruction> const& instructio
uint32_t start_side_effect_counter =
!public_inputs_vec.empty() ? static_cast<uint32_t>(public_inputs_vec[PCPI_START_SIDE_EFFECT_COUNTER_OFFSET])
: 0;
AvmTraceBuilder trace_builder(public_inputs, execution_hints, start_side_effect_counter);
AvmTraceBuilder trace_builder(public_inputs, execution_hints, start_side_effect_counter, calldata);

// Copied version of pc maintained in trace builder. The value of pc is evolving based
// on opcode logic and therefore is not maintained here. However, the next opcode in the execution
Expand Down Expand Up @@ -436,8 +436,7 @@ std::vector<Row> Execution::gen_trace(std::vector<Instruction> const& instructio
trace_builder.op_calldata_copy(std::get<uint8_t>(inst.operands.at(0)),
std::get<uint32_t>(inst.operands.at(1)),
std::get<uint32_t>(inst.operands.at(2)),
std::get<uint32_t>(inst.operands.at(3)),
calldata);
std::get<uint32_t>(inst.operands.at(3)));
break;
// Machine State - Gas
case OpCode::L2GASLEFT:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Execution {
std::vector<FF> const& calldata = {},
std::vector<FF> const& public_inputs_vec = getDefaultPublicInputs(),
ExecutionHints const& execution_hints = {});
static bool verify(AvmFlavor::VerificationKey vk, HonkProof const& proof);
static bool verify(AvmFlavor::VerificationKey vk, HonkProof const& proof, std::vector<FF> const& calldata);
};

} // namespace bb::avm_trace
6 changes: 4 additions & 2 deletions barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx)
return static_cast<bool>((ind_value & (1 << operand_idx)) >> operand_idx);
}

std::vector<std::vector<FF>> copy_public_inputs_columns(VmPublicInputs const& public_inputs)
std::vector<std::vector<FF>> copy_public_inputs_columns(VmPublicInputs const& public_inputs,
std::vector<FF> const& calldata)
{
// We convert to a vector as the pil generated verifier is generic and unaware of the KERNEL_INPUTS_LENGTH
// For each of the public input vectors
Expand All @@ -158,7 +159,8 @@ std::vector<std::vector<FF>> copy_public_inputs_columns(VmPublicInputs const& pu
return { std::move(public_inputs_kernel_inputs),
std::move(public_inputs_kernel_value_outputs),
std::move(public_inputs_kernel_side_effect_outputs),
std::move(public_inputs_kernel_metadata_outputs) };
std::move(public_inputs_kernel_metadata_outputs),
calldata };
}

} // namespace bb::avm_trace
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx);
// There are 4 public input columns, one for inputs, and 3 for the kernel outputs {value, side effect counter, metadata}
// The verifier is generic, and so accepts vectors of these values rather than the fixed length arrays that are used
// during circuit building. This method copies each array into a vector to be used by the verifier.
std::vector<std::vector<FF>> copy_public_inputs_columns(VmPublicInputs const& public_inputs);
std::vector<std::vector<FF>> copy_public_inputs_columns(VmPublicInputs const& public_inputs,
std::vector<FF> const& calldata);

} // namespace bb::avm_trace
51 changes: 39 additions & 12 deletions barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ namespace bb::avm_trace {
*/
AvmTraceBuilder::AvmTraceBuilder(VmPublicInputs public_inputs,
ExecutionHints execution_hints,
uint32_t side_effect_counter)
uint32_t side_effect_counter,
std::vector<FF> calldata)
// NOTE: we initialise the environment builder here as it requires public inputs
: kernel_trace_builder(std::move(public_inputs))
, calldata(std::move(calldata))
, side_effect_counter(side_effect_counter)
, initial_side_effect_counter(side_effect_counter)
, execution_hints(std::move(execution_hints))
Expand Down Expand Up @@ -1886,10 +1888,8 @@ void AvmTraceBuilder::op_div(
* @param cd_offset The starting index of the region in calldata to be copied.
* @param copy_size The number of finite field elements to be copied into memory.
* @param dst_offset The starting index of memory where calldata will be copied to.
* @param call_data_mem The vector containing calldata.
*/
void AvmTraceBuilder::op_calldata_copy(
uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset, std::vector<FF> const& call_data_mem)
void AvmTraceBuilder::op_calldata_copy(uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset)
{
// We parallelize storing memory operations in chunk of 3, i.e., 1 per intermediate register.
// The variable pos is an index pointing to the first storing operation (pertaining to intermediate
Expand All @@ -1912,7 +1912,7 @@ void AvmTraceBuilder::op_calldata_copy(
uint32_t rwc(0);
auto clk = static_cast<uint32_t>(main_trace.size()) + 1;

FF ia = call_data_mem.at(cd_offset + pos);
FF ia = calldata.at(cd_offset + pos);
uint32_t mem_op_a(1);
uint32_t rwa = 1;

Expand All @@ -1934,7 +1934,7 @@ void AvmTraceBuilder::op_calldata_copy(
call_ptr, clk, IntermRegister::IA, mem_addr_a, ia, AvmMemoryTag::U0, AvmMemoryTag::FF);

if (copy_size - pos > 1) {
ib = call_data_mem.at(cd_offset + pos + 1);
ib = calldata.at(cd_offset + pos + 1);
mem_op_b = 1;
mem_addr_b = direct_dst_offset + pos + 1;
rwb = 1;
Expand All @@ -1945,7 +1945,7 @@ void AvmTraceBuilder::op_calldata_copy(
}

if (copy_size - pos > 2) {
ic = call_data_mem.at(cd_offset + pos + 2);
ic = calldata.at(cd_offset + pos + 2);
mem_op_c = 1;
mem_addr_c = direct_dst_offset + pos + 2;
rwc = 1;
Expand Down Expand Up @@ -3762,7 +3762,9 @@ std::vector<Row> AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c

main_trace.at(*trace_size - 1).main_sel_last = FF(1);

// Memory trace inclusion
/**********************************************************************************************
* MEMORY TRACE INCLUSION
**********************************************************************************************/

// We compute in the main loop the timestamp and global address for next row.
// Perform initialization for index 0 outside of the loop provided that mem trace exists.
Expand Down Expand Up @@ -3866,7 +3868,10 @@ std::vector<Row> AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c
}
}

// Alu trace inclusion
/**********************************************************************************************
* ALU TRACE INCLUSION
**********************************************************************************************/

for (size_t i = 0; i < alu_trace_size; i++) {
auto const& src = alu_trace.at(i);
auto& dest = main_trace.at(i);
Expand Down Expand Up @@ -4013,6 +4018,10 @@ std::vector<Row> AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c
}
}

/**********************************************************************************************
* GADGET TABLES INCLUSION
**********************************************************************************************/

// Add Conversion Gadget table
for (size_t i = 0; i < conv_trace_size; i++) {
auto const& src = conv_trace.at(i);
Expand Down Expand Up @@ -4067,6 +4076,10 @@ std::vector<Row> AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c
dest.pedersen_sel_pedersen = FF(1);
}

/**********************************************************************************************
* BINARY TRACE INCLUSION
**********************************************************************************************/

// Add Binary Trace table
for (size_t i = 0; i < bin_trace_size; i++) {
auto const& src = bin_trace.at(i);
Expand Down Expand Up @@ -4132,7 +4145,9 @@ std::vector<Row> AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c
}
}

/////////// GAS ACCOUNTING //////////////////////////
/**********************************************************************************************
* GAS TRACE INCLUSION
**********************************************************************************************/

// Add the gas cost table to the main trace
// TODO: do i need a way to produce an interupt that will stop the execution of the trace when the gas left
Expand Down Expand Up @@ -4222,11 +4237,14 @@ std::vector<Row> AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c
dest.main_da_gas_remaining = current_da_gas_remaining;
}

/////////// END OF GAS ACCOUNTING //////////////////////////

// Adding extra row for the shifted values at the top of the execution trace.
Row first_row = Row{ .main_sel_first = FF(1), .mem_lastAccess = FF(1) };
main_trace.insert(main_trace.begin(), first_row);

/**********************************************************************************************
* RANGE CHECKS AND SELECTORS INCLUSION
**********************************************************************************************/

auto const old_trace_size = main_trace.size();

auto new_trace_size = range_check_required ? old_trace_size
Expand Down Expand Up @@ -4316,6 +4334,10 @@ std::vector<Row> AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c
}
}

/**********************************************************************************************
* KERNEL TRACE INCLUSION
**********************************************************************************************/

// Write the kernel trace into the main trace
// 1. The write offsets are constrained to be non changing over the entire trace, so we fill in the values
// until we
Expand Down Expand Up @@ -4494,6 +4516,11 @@ std::vector<Row> AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c
std::get<KERNEL_OUTPUTS_METADATA>(kernel_trace_builder.public_inputs).at(i);
}

// calldata column inclusion
for (size_t i = 0; i < calldata.size(); i++) {
main_trace.at(i).main_calldata = calldata.at(i);
}

// Get tag_err counts from the mem_trace_builder
if (range_check_required) {
finalise_mem_trace_lookup_counts();
Expand Down
11 changes: 5 additions & 6 deletions barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class AvmTraceBuilder {
public:
AvmTraceBuilder(VmPublicInputs public_inputs = {},
ExecutionHints execution_hints = {},
uint32_t side_effect_counter = 0);
uint32_t side_effect_counter = 0,
std::vector<FF> calldata = {});

std::vector<Row> finalize(uint32_t min_trace_size = 0, bool range_check_required = ENABLE_PROVING);
void reset();
Expand Down Expand Up @@ -158,11 +159,7 @@ class AvmTraceBuilder {
// CALLDATACOPY opcode with direct/indirect memory access, i.e.,
// direct: M[dst_offset:dst_offset+copy_size] = calldata[cd_offset:cd_offset+copy_size]
// indirect: M[M[dst_offset]:M[dst_offset]+copy_size] = calldata[cd_offset:cd_offset+copy_size]
void op_calldata_copy(uint8_t indirect,
uint32_t cd_offset,
uint32_t copy_size,
uint32_t dst_offset,
std::vector<FF> const& call_data_mem);
void op_calldata_copy(uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset);

// REVERT Opcode (that just call return under the hood for now)
std::vector<FF> op_revert(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size);
Expand Down Expand Up @@ -241,6 +238,8 @@ class AvmTraceBuilder {
AvmPedersenTraceBuilder pedersen_trace_builder;
AvmEccTraceBuilder ecc_trace_builder;

std::vector<FF> calldata{};

/**
* @brief Create a kernel lookup opcode object
*
Expand Down
Loading

0 comments on commit 2e86e25

Please sign in to comment.