Skip to content
Open
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
49 changes: 30 additions & 19 deletions barretenberg/cpp/pil/vm2/bytecode/bc_retrieval.pil
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
include "contract_instance_retrieval.pil";

include "../constants_gen.pil";
include "../trees/indexed_tree_check.pil";

// Bytecode retrieval.
//
Expand Down Expand Up @@ -97,17 +98,25 @@ pol commit remaining_bytecodes_inv;
#[NO_REMAINING_BYTECODES]
sel * (REMAINING_BYTECODES * (no_remaining_bytecodes * (1 - remaining_bytecodes_inv) + remaining_bytecodes_inv) - 1 + no_remaining_bytecodes) = 0;

pol commit is_new_class; // @boolean (by lookup into retrieved_bytecodes_tree_check when instance_exists == 1; constrained to 0 when instance_exists == 0)
pol commit is_new_class; // @boolean (by lookup into indexed_tree_check when instance_exists == 1; constrained to 0 when instance_exists == 0)

// Lookup constant support: Can be removed when we support constants in lookups.
pol commit retrieved_bytecodes_tree_height;
instance_exists * (retrieved_bytecodes_tree_height - constants.AVM_RETRIEVED_BYTECODES_TREE_HEIGHT) = 0;

#[IS_NEW_CLASS_CHECK]
instance_exists {
current_class_id,
is_new_class,
prev_retrieved_bytecodes_tree_root
} in retrieved_bytecodes_tree_check.sel {
retrieved_bytecodes_tree_check.class_id,
retrieved_bytecodes_tree_check.leaf_not_exists,
retrieved_bytecodes_tree_check.root
is_new_class, // not_exists
current_class_id, // value
prev_retrieved_bytecodes_tree_root,
retrieved_bytecodes_tree_height,
precomputed.zero // sel_silo = 0 (no siloing)
} in indexed_tree_check.sel {
indexed_tree_check.not_exists,
indexed_tree_check.value,
indexed_tree_check.root,
indexed_tree_check.tree_height,
indexed_tree_check.sel_silo
};

// Enforce is_new_class == 0 if the instance does not exist.
Expand Down Expand Up @@ -139,19 +148,21 @@ should_retrieve {

#[RETRIEVED_BYTECODES_INSERTION]
should_retrieve {
current_class_id,
should_retrieve, // 1
current_class_id, // value
prev_retrieved_bytecodes_tree_root,
prev_retrieved_bytecodes_tree_size,
next_retrieved_bytecodes_tree_root,
next_retrieved_bytecodes_tree_size
} in retrieved_bytecodes_tree_check.sel {
retrieved_bytecodes_tree_check.class_id,
retrieved_bytecodes_tree_check.write,
retrieved_bytecodes_tree_check.root,
retrieved_bytecodes_tree_check.tree_size_before_write,
retrieved_bytecodes_tree_check.write_root,
retrieved_bytecodes_tree_check.tree_size_after_write
prev_retrieved_bytecodes_tree_size,
next_retrieved_bytecodes_tree_size,
retrieved_bytecodes_tree_height,
precomputed.zero // sel_silo = 0 (no siloing)
} in indexed_tree_check.write {
indexed_tree_check.value,
indexed_tree_check.root,
indexed_tree_check.write_root,
indexed_tree_check.tree_size_before_write,
indexed_tree_check.tree_size_after_write,
indexed_tree_check.tree_height,
indexed_tree_check.sel_silo
};

// If instance does not exist, force current_class_id to 0.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,20 +129,32 @@ namespace contract_instance_retrieval;
// Protocol contracts do not have an address nullifier in the nullifier tree.
should_check_nullifier = sel * (1 - is_protocol_contract);

// Lookup constant support: Can be removed when we support constants in lookups.
pol commit nullifier_tree_height;
should_check_nullifier * (nullifier_tree_height - constants.NULLIFIER_TREE_HEIGHT) = 0;

// Lookup constant support: Can be removed when we support constants in lookups.
pol commit siloing_separator;
should_check_nullifier * (siloing_separator - constants.DOM_SEP__SILOED_NULLIFIER) = 0;

// Nullifier existence check (deployment nullifier read)
#[DEPLOYMENT_NULLIFIER_READ]
should_check_nullifier {
exists, // does the contract address nullifier exist? gates later lookups....
address, // the deployment nullifier
nullifier_tree_root,
deployer_protocol_contract_address,
sel // 1 (yes silo)
} in nullifier_check.sel {
nullifier_check.exists,
nullifier_check.nullifier,
nullifier_check.root,
nullifier_check.address,
nullifier_check.sel_silo
nullifier_tree_height,
sel, // 1 (yes silo)
siloing_separator,
deployer_protocol_contract_address
} in indexed_tree_check.sel {
indexed_tree_check.exists,
indexed_tree_check.value,
indexed_tree_check.root,
indexed_tree_check.tree_height,
indexed_tree_check.sel_silo,
indexed_tree_check.siloing_separator,
indexed_tree_check.address
};

// For protocol contracts we retrieve the derived address from the protocol contract trace, else use the input address
Expand Down
39 changes: 28 additions & 11 deletions barretenberg/cpp/pil/vm2/execution.pil
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@ include "execution/gas.pil";
include "execution/registers.pil";

include "trees/merkle_check.pil";
include "trees/nullifier_check.pil";
include "trees/indexed_tree_check.pil";
include "trees/public_data_check.pil";
include "trees/written_public_data_slots_tree_check.pil";
include "trees/l1_to_l2_message_tree_check.pil";
include "trees/retrieved_bytecodes_tree_check.pil";

include "bytecode/address_derivation.pil";
include "bytecode/bc_decomposition.pil";
Expand Down Expand Up @@ -517,21 +515,36 @@ sel_gas_to_radix * ((/*num_limbs=*/register[2] - num_p_limbs) * sel_use_num_limb
//////////////////////////////////////////
// SSTORE, Dynamic DA Gas Calculation
//////////////////////////////////////////

// Lookup constant support: Can be removed when we support constants in lookups.
pol commit written_slots_tree_height;
sel_gas_sstore * (written_slots_tree_height - constants.AVM_WRITTEN_PUBLIC_DATA_SLOTS_TREE_HEIGHT) = 0;

// Lookup constant support: Can be removed when we support constants in lookups.
pol commit written_slots_tree_siloing_separator;
sel_gas_sstore * (written_slots_tree_siloing_separator - constants.DOM_SEP__PUBLIC_LEAF_SLOT) = 0;

// We can probably unconditionally write to the written_public_data_slots_tree here
// to avoid writing later in opcode execution, since the root would be reverted if it errors before
// the opcode execution. However, this feels like an early optimization
// since the simulator would need to write at the gas step which is a bit weird.
#[CHECK_WRITTEN_STORAGE_SLOT]
sel_gas_sstore {
contract_address,
register[1], // slot
dynamic_da_gas_factor,
prev_written_public_data_slots_tree_root
} in written_public_data_slots_tree_check.sel {
written_public_data_slots_tree_check.address,
written_public_data_slots_tree_check.slot,
written_public_data_slots_tree_check.leaf_not_exists,
written_public_data_slots_tree_check.root
register[1], // value
prev_written_public_data_slots_tree_root,
written_slots_tree_height,
sel_gas_sstore, // sel_silo = 1
written_slots_tree_siloing_separator,
contract_address
} in indexed_tree_check.sel {
indexed_tree_check.not_exists,
indexed_tree_check.value,
indexed_tree_check.root,
indexed_tree_check.tree_height,
indexed_tree_check.sel_silo,
indexed_tree_check.siloing_separator,
indexed_tree_check.address
};

///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -775,6 +788,10 @@ sel_execute_returndata_size * (mem_tag_reg[0] - constants.MEM_TAG_U32) = 0; // W
#[RETRIEVED_BYTECODES_TREE_SIZE_NOT_CHANGED]
(1 - sel_first_row_in_context) * (prev_retrieved_bytecodes_tree_size - retrieved_bytecodes_tree_size) = 0;

// Shared between nullifier_exists.pil and emit_nullifier.pil.
// Lookup constant support: Can be removed when we support constants in lookups.
pol commit nullifier_tree_height;

// Whether the opcode logic failed.
pol commit sel_opcode_error; // @boolean
sel_opcode_error * (1 - sel_opcode_error) = 0;
Expand Down
54 changes: 34 additions & 20 deletions barretenberg/cpp/pil/vm2/opcodes/emit_nullifier.pil
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ include "../constants_gen.pil";
* - register[0] as the nullifier input register (FF)
*
* Interactions:
* - The gadget performs a lookup into the nullifier_check gadget to attempt to write the nullifier.
* - The gadget performs a lookup into the indexed_tree_check gadget to attempt to write the nullifier.
* - This lookup is only performed if no limit error occurs.
*
* Errors:
Expand Down Expand Up @@ -54,28 +54,42 @@ namespace execution; // this is a virtual gadget that shares rows with the execu

// =========== OPCODE EXECUTION ===========

pol commit nullifier_pi_offset;
sel_write_nullifier * (constants.AVM_PUBLIC_INPUTS_AVM_ACCUMULATED_DATA_NULLIFIERS_ROW_IDX + prev_num_nullifiers_emitted - nullifier_pi_offset) = 0;

// From execution.pil.
sel_write_nullifier * (nullifier_tree_height - constants.NULLIFIER_TREE_HEIGHT) = 0;

// Lookup constant support: Can be removed when we support constants in lookups.
pol commit nullifier_siloing_separator;
sel_write_nullifier * (nullifier_siloing_separator - constants.DOM_SEP__SILOED_NULLIFIER) = 0;

// Lookup into nullifier tree check to attempt write
#[WRITE_NULLIFIER]
sel_write_nullifier {
/*nullifier=*/ register[0], // input: nullifier to write
prev_nullifier_tree_root, // input: pre-write tree root (from context.pil)
/*exists=*/ sel_opcode_error, // output: 1 if nullifier already exists (error)
nullifier_tree_root, // output: new tree root (updates context.pil column!)
prev_nullifier_tree_size, // input: pre-write tree size (from context.pil)
discard, // input: (from execution_discard) will this write eventually be reverted (so it shouldn't be written to public inputs)?
/*nullifier_index=*/ prev_num_nullifiers_emitted, // input: the nullifier index to write to in public inputs
/*sel_silo=1*/ sel_write_nullifier, // input: sel_silo = 1 (always silo for contract nullifiers)
contract_address // input: contract address for siloing (from context)
} in nullifier_check.write {
nullifier_check.nullifier,
nullifier_check.root,
nullifier_check.exists, // nullifier collision
nullifier_check.write_root, // post-write tree root
nullifier_check.tree_size_before_write,
nullifier_check.discard,
nullifier_check.nullifier_index, // index to write to in public inputs
nullifier_check.sel_silo,
nullifier_check.address // contract address for siloing
/*nullifier=*/ register[0], // input: nullifier to write
prev_nullifier_tree_root, // input: pre-write tree root (from context.pil)
/*exists=*/ sel_opcode_error, // output: 1 if nullifier already exists (error)
nullifier_tree_root, // output: new tree root (updates context.pil column!)
prev_nullifier_tree_size, // input: pre-write tree size (from context.pil)
discard, // input: (from execution_discard) will this write eventually be reverted (so it shouldn't be written to public inputs)?
nullifier_pi_offset, // input: the index to write to in public inputs
nullifier_tree_height, // input: the tree height
/*sel_silo=1*/ sel_write_nullifier, // input: sel_silo = 1 (always silo for contract nullifiers)
nullifier_siloing_separator, // input: siloing separator
contract_address // input: contract address for siloing (from context)
} in indexed_tree_check.write {
indexed_tree_check.value,
indexed_tree_check.root,
indexed_tree_check.exists, // nullifier collision
indexed_tree_check.write_root, // post-write tree root
indexed_tree_check.tree_size_before_write,
indexed_tree_check.discard,
indexed_tree_check.public_inputs_index, // index to write to in public inputs
indexed_tree_check.tree_height,
indexed_tree_check.sel_silo,
indexed_tree_check.siloing_separator,
indexed_tree_check.address // contract address for siloing
};

pol SUCCESSFUL_WRITE = sel_write_nullifier * (1 - sel_opcode_error);
Expand Down
24 changes: 14 additions & 10 deletions barretenberg/cpp/pil/vm2/opcodes/nullifier_exists.pil
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ include "../constants_gen.pil";
*
* Memory reads and writes are handled by standard execution logic.
*
* The gadget performs a lookup into the nullifier_check gadget to determine if the nullifier
* The gadget performs a lookup into the indexed_tree_check gadget to determine if the nullifier
* exists. The nullifier is already siloed by the caller (no siloing happens in this opcode).
* The result is written to the output register.
*
Expand All @@ -27,23 +27,27 @@ namespace execution; // this is a virtual gadget that shares rows with the execu
#[skippable_if]
sel_execute_nullifier_exists = 0; // from execution.pil.

// From execution.pil.
sel_execute_nullifier_exists * (nullifier_tree_height - constants.NULLIFIER_TREE_HEIGHT) = 0;

// Lookup into nullifier tree check to determine existence
#[NULLIFIER_EXISTS_CHECK]
sel_execute_nullifier_exists {
// Outputs
/*exists=*/ register[1], // output: whether nullifier exists
/*exists=*/ register[1], // output: whether nullifier exists
// Inputs
/*nullifier=*/ register[0], // input: siloed nullifier to check
prev_nullifier_tree_root, // input: tree root from context
/*sel_silo=0*/ precomputed.zero // input: sel_silo = 0 (nullifier is already siloed, address also omitted)
} in nullifier_check.sel {
/*value=*/ register[0], // input: siloed nullifier to check
prev_nullifier_tree_root, // input: tree root from context
nullifier_tree_height, // input: tree height
/*sel_silo=0*/ precomputed.zero // input: sel_silo = 0 (nullifier is already siloed, address and separator omitted)
} in indexed_tree_check.sel {
// Outputs
nullifier_check.exists,
indexed_tree_check.exists,
// Inputs
nullifier_check.nullifier,
nullifier_check.root,
nullifier_check.sel_silo
indexed_tree_check.value,
indexed_tree_check.root,
indexed_tree_check.tree_height,
indexed_tree_check.sel_silo
};

// Tag result (`exists`) as u1 (via mem_tag_reg[1]).
Expand Down
32 changes: 18 additions & 14 deletions barretenberg/cpp/pil/vm2/opcodes/sstore.pil
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
include "../constants_gen.pil";
include "../trees/public_data_check.pil";
include "../trees/written_public_data_slots_tree_check.pil";
include "../trees/indexed_tree_check.pil";

// SSTORE opcode: Writes a value to storage at the provided slot
//
Expand All @@ -14,7 +14,7 @@ include "../trees/written_public_data_slots_tree_check.pil";
// - register[1]: Contains the storage slot to write to
//
// The opcode leverages the public_data_check gadget to verify the storage write operation
// and the written_public_data_slots_tree_check gadget to track written slots for gas calculation.
// and the indexed_tree_check gadget to track written slots for gas calculation.
//
namespace execution; // this is a virtual gadget that shares rows with the execution trace

Expand Down Expand Up @@ -55,21 +55,25 @@ namespace execution; // this is a virtual gadget that shares rows with the execu

#[RECORD_WRITTEN_STORAGE_SLOT]
sel_write_public_data {
contract_address,
register[1], // slot
sel_write_public_data/*=1*/,
prev_written_public_data_slots_tree_root,
prev_written_public_data_slots_tree_size,
written_public_data_slots_tree_root,
written_public_data_slots_tree_size
} in written_public_data_slots_tree_check.sel {
written_public_data_slots_tree_check.address,
written_public_data_slots_tree_check.slot,
written_public_data_slots_tree_check.write,
written_public_data_slots_tree_check.root,
written_public_data_slots_tree_check.tree_size_before_write,
written_public_data_slots_tree_check.write_root,
written_public_data_slots_tree_check.tree_size_after_write
prev_written_public_data_slots_tree_size,
written_public_data_slots_tree_size,
written_slots_tree_height, // From execution.pil. Gated by sel_gas_sstore, which is a requirement for sel_write_public_data.
sel_write_public_data, // sel_silo = 1
written_slots_tree_siloing_separator, // From execution.pil. Gated by sel_gas_sstore, which is a requirement for sel_write_public_data.
contract_address
} in indexed_tree_check.write {
indexed_tree_check.value,
indexed_tree_check.root,
indexed_tree_check.write_root,
indexed_tree_check.tree_size_before_write,
indexed_tree_check.tree_size_after_write,
indexed_tree_check.tree_height,
indexed_tree_check.sel_silo,
indexed_tree_check.siloing_separator,
indexed_tree_check.address
};

#[STORAGE_WRITE]
Expand Down
8 changes: 3 additions & 5 deletions barretenberg/cpp/pil/vm2/poseidon2_hash.pil
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ include "precomputed.pil";
* output, input_len and use destination selector start (= 1). The caller will pass 1,2, or 3 for input_len. This follows
* from the below constraints that `num_perm_rounds_rem == 1` and `end ==1`.
*
* Example (nullifier_check.pil):
* sel_silo { siloing_separator, address, nullifier, siloed_nullifier, const_three }
* Example (indexed_tree_check.pil):
* sel_silo { siloing_separator, address, value, siloed_value, const_three }
* in poseidon2_hash.start { poseidon2_hash.input_0, poseidon2_hash.input_1,
* poseidon2_hash.input_2, poseidon2_hash.output, poseidon2_hash.input_len };
*
Expand Down Expand Up @@ -56,12 +56,10 @@ include "precomputed.pil";
* - class_id_derivation.pil
* - merkle_check.pil
* - note_hash_tree_check.pil
* - nullifier_check.pil
* - indexed_tree_check.pil
* - public_data_check.pil
* - retrieved_bytecodes_tree_check.pil
* - tx.pil
* - update_check.pil
* - written_public_data_slots_tree_check.pil
*/
namespace poseidon2_hash;

Expand Down
Loading