Skip to content

Commit

Permalink
feat(vm): executor for public kernel inputs (#6716)
Browse files Browse the repository at this point in the history
## Overview 
Adds executor for public kernel inputs 

This executor runs using public_inputs_vec which will be the entire
`PublicCircuitPublicInputs` that the ts vm simulator should have crafted
after execution.

---------

Co-authored-by: Jean M <[email protected]>
  • Loading branch information
Maddiaa0 and jeanmon authored May 30, 2024
1 parent 9ee76f2 commit d3bc173
Show file tree
Hide file tree
Showing 8 changed files with 399 additions and 14 deletions.
1 change: 1 addition & 0 deletions barretenberg/cpp/pil/avm/constants.pil
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace constants(256);
pol START_SIDE_EFFECT_COUNTER = 37;

// Gas
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6715): This has since moved into the global variables
pol FEE_PER_DA_GAS_SELECTOR = 38;
pol FEE_PER_L2_GAS_SELECTOR = 39;

Expand Down
113 changes: 110 additions & 3 deletions barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
#include "barretenberg/common/serialize.hpp"
#include "barretenberg/vm/avm_trace/avm_common.hpp"
#include "barretenberg/vm/avm_trace/avm_deserialization.hpp"
#include "barretenberg/vm/avm_trace/avm_instructions.hpp"
#include "barretenberg/vm/avm_trace/avm_kernel_trace.hpp"
#include "barretenberg/vm/avm_trace/avm_opcode.hpp"
#include "barretenberg/vm/avm_trace/avm_trace.hpp"
#include "barretenberg/vm/avm_trace/aztec_constants.hpp"
#include "barretenberg/vm/avm_trace/constants.hpp"
#include "barretenberg/vm/generated/avm_circuit_builder.hpp"
#include "barretenberg/vm/generated/avm_composer.hpp"
#include "barretenberg/vm/generated/avm_flavor.hpp"
Expand Down Expand Up @@ -60,6 +64,70 @@ bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof)
return verifier.verify_proof(proof, public_inputs_vec);
}

/**
* @brief Convert Public Inputs
*
* **Transitional**
* Converts public inputs from the public inputs vec (PublicCircuitPublicInputs) into it's respective public input
* columns Which are represented by the `VmPublicInputs` object.
*
* @param public_inputs_vec
* @return VmPublicInputs
*/
VmPublicInputs convert_public_inputs(std::vector<FF> const& public_inputs_vec)
{
VmPublicInputs public_inputs = {};

// Case where we pass in empty public inputs - this will be used in tests where they are not required
if (public_inputs_vec.empty()) {
return public_inputs;
}

// Convert the public inputs into the VmPublicInputs object, the public inputs vec must be the correct length - else
// we throw an exception
if (public_inputs_vec.size() != PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH) {
throw_or_abort("Public inputs vector is not of PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH");
}

std::array<FF, KERNEL_INPUTS_LENGTH>& kernel_inputs = std::get<KERNEL_INPUTS>(public_inputs);

// Copy the call context items
kernel_inputs[SENDER_SELECTOR] = public_inputs_vec[SENDER_SELECTOR]; // Sender
kernel_inputs[ADDRESS_SELECTOR] = public_inputs_vec[ADDRESS_SELECTOR]; // Address

// Global variables
kernel_inputs[CHAIN_ID_SELECTOR] = public_inputs_vec[CHAIN_ID_OFFSET]; // Chain ID
kernel_inputs[VERSION_SELECTOR] = public_inputs_vec[VERSION_OFFSET]; // Version
kernel_inputs[BLOCK_NUMBER_SELECTOR] = public_inputs_vec[BLOCK_NUMBER_OFFSET]; // Block Number
kernel_inputs[TIMESTAMP_SELECTOR] = public_inputs_vec[TIMESTAMP_OFFSET]; // Timestamp
kernel_inputs[COINBASE_SELECTOR] = public_inputs_vec[COINBASE_OFFSET]; // Coinbase

// Fees
kernel_inputs[FEE_PER_DA_GAS_SELECTOR] = public_inputs_vec[FEE_PER_DA_GAS_OFFSET];
kernel_inputs[FEE_PER_L2_GAS_SELECTOR] = public_inputs_vec[FEE_PER_L2_GAS_OFFSET];

// Transaction fee
kernel_inputs[TRANSACTION_FEE_SELECTOR] = public_inputs_vec[TRANSACTION_FEE_OFFSET];

return public_inputs;
}

/**
* @brief Generate the execution trace pertaining to the supplied instructions.
*
* @param instructions A vector of the instructions to be executed.
* @param calldata expressed as a vector of finite field elements.
* @param public_inputs expressed as a vector of finite field elements.
* @return The trace as a vector of Row.
*/
std::vector<Row> Execution::gen_trace(std::vector<Instruction> const& instructions,
std::vector<FF> const& calldata,
std::vector<FF> const& public_inputs)
{
std::vector<FF> returndata{};
return gen_trace(instructions, returndata, calldata, public_inputs);
}

/**
* @brief Generate the execution trace pertaining to the supplied instructions.
*
Expand All @@ -70,22 +138,28 @@ bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof)
std::vector<Row> Execution::gen_trace(std::vector<Instruction> const& instructions, std::vector<FF> const& calldata)
{
std::vector<FF> returndata{};
return gen_trace(instructions, returndata, calldata);
std::vector<FF> public_inputs_vec = {};
return gen_trace(instructions, returndata, calldata, public_inputs_vec);
}

/**
* @brief Generate the execution trace pertaining to the supplied instructions returns the return data.
*
* @param instructions A vector of the instructions to be executed.
* @param calldata expressed as a vector of finite field elements.
* @param public_inputs expressed as a vector of finite field elements.
* @return The trace as a vector of Row.
*/
std::vector<Row> Execution::gen_trace(std::vector<Instruction> const& instructions,
std::vector<FF>& returndata,
std::vector<FF> const& calldata)
std::vector<FF> const& calldata,
std::vector<FF> const& public_inputs_vec)

{
AvmTraceBuilder trace_builder;
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6718): construction of the public input columns
// should be done in the kernel - this is stubbed and underconstrained
VmPublicInputs public_inputs = convert_public_inputs(public_inputs_vec);
AvmTraceBuilder trace_builder(public_inputs);

// 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 @@ -214,6 +288,38 @@ std::vector<Row> Execution::gen_trace(std::vector<Instruction> const& instructio
std::get<uint32_t>(inst.operands.at(3)),
calldata);
break;

// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6284): support indirect for below
case OpCode::SENDER:
trace_builder.op_sender(std::get<uint32_t>(inst.operands.at(1)));
break;
case OpCode::ADDRESS:
trace_builder.op_address(std::get<uint32_t>(inst.operands.at(1)));
break;
case OpCode::FEEPERL2GAS:
trace_builder.op_fee_per_l2_gas(std::get<uint32_t>(inst.operands.at(1)));
break;
case OpCode::FEEPERDAGAS:
trace_builder.op_fee_per_da_gas(std::get<uint32_t>(inst.operands.at(1)));
break;
case OpCode::TRANSACTIONFEE:
trace_builder.op_transaction_fee(std::get<uint32_t>(inst.operands.at(1)));
break;
case OpCode::CHAINID:
trace_builder.op_chain_id(std::get<uint32_t>(inst.operands.at(1)));
break;
case OpCode::VERSION:
trace_builder.op_version(std::get<uint32_t>(inst.operands.at(1)));
break;
case OpCode::BLOCKNUMBER:
trace_builder.op_block_number(std::get<uint32_t>(inst.operands.at(1)));
break;
case OpCode::COINBASE:
trace_builder.op_coinbase(std::get<uint32_t>(inst.operands.at(1)));
break;
case OpCode::TIMESTAMP:
trace_builder.op_timestamp(std::get<uint32_t>(inst.operands.at(1)));
break;
// Machine State - Internal Control Flow
case OpCode::JUMP:
trace_builder.jump(std::get<uint32_t>(inst.operands.at(0)));
Expand Down Expand Up @@ -323,6 +429,7 @@ std::vector<Row> Execution::gen_trace(std::vector<Instruction> const& instructio
break;
}
}

return trace_builder.finalize();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ class Execution {

static std::vector<Row> gen_trace(std::vector<Instruction> const& instructions,
std::vector<FF>& returndata,
std::vector<FF> const& calldata = {});
std::vector<FF> const& calldata,
std::vector<FF> const& public_inputs);
static std::vector<Row> gen_trace(std::vector<Instruction> const& instructions,
std::vector<FF> const& calldata = {});
static std::vector<Row> gen_trace(std::vector<Instruction> const& instructions,
std::vector<FF> const& calldata,
std::vector<FF> const& public_inputs);
static std::tuple<AvmFlavor::VerificationKey, bb::HonkProof> prove(std::vector<uint8_t> const& bytecode,
std::vector<FF> const& calldata = {});
static bool verify(AvmFlavor::VerificationKey vk, HonkProof const& proof);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ inline const uint32_t COINBASE_SELECTOR = START_GLOBAL_VARIABLES + 4;
inline const uint32_t END_GLOBAL_VARIABLES = START_GLOBAL_VARIABLES + GLOBAL_VARIABLES_LENGTH;
inline const uint32_t START_SIDE_EFFECT_COUNTER = END_GLOBAL_VARIABLES;

// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6715): update these to come from the global inputs
inline const uint32_t FEE_PER_DA_GAS_SELECTOR = START_SIDE_EFFECT_COUNTER + 1;
inline const uint32_t FEE_PER_L2_GAS_SELECTOR = FEE_PER_DA_GAS_SELECTOR + 1;
inline const uint32_t TRANSACTION_FEE_SELECTOR = FEE_PER_L2_GAS_SELECTOR + 1;
Expand Down
18 changes: 18 additions & 0 deletions barretenberg/cpp/src/barretenberg/vm/avm_trace/aztec_constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,34 @@ const size_t MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 32;
const size_t MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 32;
const size_t MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 32;
const size_t MAX_UNENCRYPTED_LOGS_PER_CALL = 4;
const size_t MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL = 16;
const size_t AZTEC_ADDRESS_LENGTH = 1;
const size_t GAS_FEES_LENGTH = 2;
const size_t GAS_LENGTH = 2;
const size_t CALL_CONTEXT_LENGTH = 6;
const size_t CONTENT_COMMITMENT_LENGTH = 4;
const size_t CONTRACT_STORAGE_READ_LENGTH = 2;
const size_t CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 2;
const size_t GLOBAL_VARIABLES_LENGTH = 6 + GAS_FEES_LENGTH;
const size_t APPEND_ONLY_TREE_SNAPSHOT_LENGTH = 2;
const size_t L2_TO_L1_MESSAGE_LENGTH = 3;
const size_t PARTIAL_STATE_REFERENCE_LENGTH = 6;
const size_t READ_REQUEST_LENGTH = 2;
const size_t LOG_HASH_LENGTH = 3;
const size_t NOTE_HASH_LENGTH = 2;
const size_t NULLIFIER_LENGTH = 3;
const size_t STATE_REFERENCE_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH;
const size_t TOTAL_FEES_LENGTH = 1;
const size_t HEADER_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH +
GLOBAL_VARIABLES_LENGTH + TOTAL_FEES_LENGTH;
const size_t PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH =
CALL_CONTEXT_LENGTH + 2 + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) +
(READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) +
(CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) +
(CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL +
(NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) +
(L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) +
HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + 2 * GAS_LENGTH +
/* transaction_fee */ 1;
const size_t PUBLIC_CONTEXT_INPUTS_LENGTH =
CALL_CONTEXT_LENGTH + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + GAS_LENGTH + 2;
17 changes: 17 additions & 0 deletions barretenberg/cpp/src/barretenberg/vm/avm_trace/constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,20 @@ inline const std::size_t KERNEL_OUTPUTS_LENGTH =
MAX_NOTE_HASH_READ_REQUESTS_PER_CALL + MAX_NEW_NOTE_HASHES_PER_CALL + MAX_NULLIFIER_READ_REQUESTS_PER_CALL +
MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL + MAX_NEW_NULLIFIERS_PER_CALL + MAX_NEW_L2_TO_L1_MSGS_PER_CALL +
MAX_UNENCRYPTED_LOGS_PER_CALL + MAX_PUBLIC_DATA_READS_PER_CALL + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL;

// START INDEXES in the PUBLIC_CIRCUIT_PUBLIC_INPUTS
// These line up with indexes found in
// https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts
inline const uint32_t PCPI_GLOBALS_START = PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH - 7 - GLOBAL_VARIABLES_LENGTH;

inline const uint32_t CHAIN_ID_OFFSET = PCPI_GLOBALS_START;
inline const uint32_t VERSION_OFFSET = PCPI_GLOBALS_START + 1;
inline const uint32_t BLOCK_NUMBER_OFFSET = PCPI_GLOBALS_START + 2;
inline const uint32_t TIMESTAMP_OFFSET = PCPI_GLOBALS_START + 3;
inline const uint32_t COINBASE_OFFSET = PCPI_GLOBALS_START + 4;

inline const uint32_t FEE_PER_DA_GAS_OFFSET = PCPI_GLOBALS_START + 6;
inline const uint32_t FEE_PER_L2_GAS_OFFSET = PCPI_GLOBALS_START + 7;

inline const uint32_t TRANSACTION_FEE_OFFSET = PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH - 1;
// END INDEXES in the PUBLIC_CIRCUIT_PUBLIC_INPUTS
Loading

0 comments on commit d3bc173

Please sign in to comment.