Skip to content

Commit bf5dea6

Browse files
authored
feat: merge-train/avm (#21116)
BEGIN_COMMIT_OVERRIDE fix(avm)!: memory pre-audit (#21058) fix(avm)!: memory trace changes (#21059) fix!: AVM was missing range check on remainder for div in ALU (#21074) feat: run AVM NAPI simulations on dedicated threads instead of libuv pool (#21138) feat(avm)!: Unify nullifier, written slots and retrieved bytecodes tree traces (#20949) fix(avm)!: public inputs pre-audit (#21162) END_COMMIT_OVERRIDE
2 parents db5b6b1 + b4a6607 commit bf5dea6

127 files changed

Lines changed: 4214 additions & 6453 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

barretenberg/cpp/pil/vm2/alu.pil

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,12 @@ pol DIV_OPS_NON_U128 = (1 - sel_err) * sel_op_fdiv + sel_div_no_err * IS_NOT_U12
434434
#[ALU_FDIV_DIV_NON_U128]
435435
DIV_OPS_NON_U128 * (ib * ic - ia + sel_op_div * helper1) = 0;
436436

437+
// Range check that the remainder (helper1) fits within max_bits (and importantly, always within 128 bits).
438+
// Without this, a malicious prover could set helper1 to an arbitrary field element that satisfies
439+
// the division relation. The GT gadget has a precondition that inputs must fit wiithin 128 bits.
440+
#[RANGE_CHECK_DIV_REMAINDER]
441+
sel_div_no_err { helper1, max_bits } in range_check.sel_alu { range_check.value, range_check.rng_chk_bits };
442+
437443
// ------------------------------------------------------------
438444
// EQ
439445
// ------------------------------------------------------------

barretenberg/cpp/pil/vm2/bytecode/bc_retrieval.pil

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ include "class_id_derivation.pil";
33

44
include "../constants_gen.pil";
55
include "../precomputed.pil";
6-
include "../trees/retrieved_bytecodes_tree_check.pil";
6+
include "../trees/indexed_tree_check.pil";
77

88
/**
99
* This subtrace constrains everything related to "retrieving" a bytecode given an address. It is responsible for proving success or failure of retrieval for a bytecode id
1010
* and does not fetch the bytes themselves. In practice this means we:
1111
* - Silo the address:
1212
* - siloed_nullifier = H(DOM_SEP__SILOED_NULLIFIER, deployer_protocol_contract_address, address)
13-
* - Enforced by lookup into contract_instance_retrieval.pil (#[CONTRACT_INSTANCE_RETRIEVAL]), which looks up nullifier_check.pil (#[DEPLOYMENT_NULLIFIER_READ]).
13+
* - Enforced by lookup into contract_instance_retrieval.pil (#[CONTRACT_INSTANCE_RETRIEVAL]), which looks up indexed_tree_check.pil (#[DEPLOYMENT_NULLIFIER_READ]).
1414
* - Check if the nullifier exists.
15-
* - Enforced in above lookup (contract_instance_retrieval.pil (#[CONTRACT_INSTANCE_RETRIEVAL]) -> nullifier_check.pil (#[DEPLOYMENT_NULLIFIER_READ])).
15+
* - Enforced in above lookup (contract_instance_retrieval.pil (#[CONTRACT_INSTANCE_RETRIEVAL]) -> indexed_tree_check.pil (#[DEPLOYMENT_NULLIFIER_READ])).
1616
* - Derive the address.
1717
* - Enforced in above lookup (contract_instance_retrieval.pil (#[CONTRACT_INSTANCE_RETRIEVAL]) -> address_derivation.pil (#[ADDRESS_DERIVATION])).
1818
* - Note: for this trace, we only 'care' about the contract instance member current_class_id (not salt, deployer_addr, init_hash), which is validated in
@@ -63,10 +63,10 @@ include "../trees/retrieved_bytecodes_tree_check.pil";
6363
* TRACE SHAPE: This subtrace retrieves one bytecode instance per row, anchored by the bytecode_id column.
6464
*
6565
* INTERACTIONS:
66-
* execution.pil --> bc_retrieval.pil --> contract_instance_retrieval.pil --> nullifier_check.pil
66+
* execution.pil --> bc_retrieval.pil --> contract_instance_retrieval.pil --> indexed_tree_check.pil
6767
* --> address_derivation.pil
6868
* --> update_check.pil
69-
* --> retrieved_bytecodes_tree_check.pil
69+
* --> indexed_tree_check.pil
7070
* --> class_id_derivation.pil
7171
* --> instr_fetching.pil --> bc_decomposition.pil <-> bc_hashing.pil
7272
* --> precomputed.pil
@@ -81,9 +81,9 @@ include "../trees/retrieved_bytecodes_tree_check.pil";
8181
* (#[CONTRACT_INSTANCE_RETRIEVAL]). Additionally links the state tree roots and enforces that the class id is zero if the
8282
* instance does not exist. This lookup is crucial since we defer the nullifier, address, and update checks to the contract
8383
* instance retrieval trace.
84-
* - retrieved_bytecodes_tree_check.pil: If an instance exists, to constrain whether it is a new class id not yet accessed by this tx (#[IS_NEW_CLASS_CHECK]).
85-
* If there is no error, to insert the class id into the retrieved bytecodes tree (#[RETRIEVED_BYTECODES_INSERTION]).
86-
* These cases must form separate lookups to ensure we do not add to the tree when we have hit the bytecode limit.
84+
* - indexed_tree_check.pil: If an instance exists, to constrain whether it is a new class id not yet accessed by this tx (#[IS_NEW_CLASS_CHECK]).
85+
* If there is no error, to insert the class id into the retrieved bytecodes tree (#[RETRIEVED_BYTECODES_INSERTION]).
86+
* These cases must form separate lookups to ensure we do not add to the tree when we have hit the bytecode limit.
8787
* - class_id_derivation.pil: If there is no error, to constrain correctness of the class id against the contract class member columns of this trace
8888
* (#[CLASS_ID_DERIVATION]). In terms of this trace's columns, that is:
8989
* current_class_id = Poseidon2(DOM_SEP__CONTRACT_CLASS_ID, artifact_hash, private_functions_root, bytecode_id),
@@ -168,7 +168,7 @@ sel {
168168
// Switching on the error column forces the class members to be zero.
169169

170170
// Whether we have retrieved the bytecode for this class before (if not, is_new_class == 1 and we insert the bytecode into the tree).
171-
pol commit is_new_class; // @boolean (by lookup into retrieved_bytecodes_tree_check when instance_exists == 1; constrained to be 0 when instance_exists == 0)
171+
pol commit is_new_class; // @boolean (by lookup into indexed_tree_check when instance_exists == 1; constrained to be 0 when instance_exists == 0)
172172

173173
// Whether we have retrieved the maximum number of different bytecodes for this tx.
174174
pol commit no_remaining_bytecodes; // @boolean
@@ -233,36 +233,46 @@ should_retrieve {
233233
// Bytecode Tree Read/Write
234234
///////////////////////////////
235235

236+
// Lookup constant support: Can be removed when we support constants in lookups.
237+
pol commit retrieved_bytecodes_tree_height;
238+
sel * (retrieved_bytecodes_tree_height - constants.AVM_RETRIEVED_BYTECODES_TREE_HEIGHT) = 0;
239+
236240
// This constrains that is_new_class is on iff the bytecode does not exist in the transient tree (i.e. this
237241
// bytecode has not been used in this tx).
238242
// Note: instance_exists can be on for inactive rows, but this lookup below not create side effects, so
239243
// it is safe to gate by instance_exists rather than sel && instance_exists.
240244
#[IS_NEW_CLASS_CHECK]
241245
instance_exists {
242-
current_class_id,
243-
is_new_class,
244-
prev_retrieved_bytecodes_tree_root
245-
} in retrieved_bytecodes_tree_check.sel {
246-
retrieved_bytecodes_tree_check.class_id,
247-
retrieved_bytecodes_tree_check.leaf_not_exists,
248-
retrieved_bytecodes_tree_check.root
246+
is_new_class, // not_exists
247+
current_class_id, // value
248+
prev_retrieved_bytecodes_tree_root,
249+
retrieved_bytecodes_tree_height,
250+
precomputed.zero // sel_silo = 0 (no siloing)
251+
} in indexed_tree_check.sel {
252+
indexed_tree_check.not_exists,
253+
indexed_tree_check.value,
254+
indexed_tree_check.root,
255+
indexed_tree_check.tree_height,
256+
indexed_tree_check.sel_silo
249257
};
250258

251259
// This constrains that if we have retrieved bytecode for a new class, we update the tree correctly.
252260
#[RETRIEVED_BYTECODES_INSERTION]
253261
should_retrieve {
254-
current_class_id,
255-
should_retrieve, /*=1*/
262+
current_class_id, // value
256263
prev_retrieved_bytecodes_tree_root,
257-
prev_retrieved_bytecodes_tree_size,
258264
next_retrieved_bytecodes_tree_root,
259-
next_retrieved_bytecodes_tree_size
260-
} in retrieved_bytecodes_tree_check.sel {
261-
retrieved_bytecodes_tree_check.class_id,
262-
retrieved_bytecodes_tree_check.write,
263-
retrieved_bytecodes_tree_check.root,
264-
retrieved_bytecodes_tree_check.tree_size_before_write,
265-
retrieved_bytecodes_tree_check.write_root,
266-
retrieved_bytecodes_tree_check.tree_size_after_write
265+
prev_retrieved_bytecodes_tree_size,
266+
next_retrieved_bytecodes_tree_size,
267+
retrieved_bytecodes_tree_height,
268+
precomputed.zero // sel_silo = 0 (no siloing)
269+
} in indexed_tree_check.write {
270+
indexed_tree_check.value,
271+
indexed_tree_check.root,
272+
indexed_tree_check.write_root,
273+
indexed_tree_check.tree_size_before_write,
274+
indexed_tree_check.tree_size_after_write,
275+
indexed_tree_check.tree_height,
276+
indexed_tree_check.sel_silo
267277
};
268278

barretenberg/cpp/pil/vm2/bytecode/contract_instance_retrieval.pil

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,20 +129,32 @@ namespace contract_instance_retrieval;
129129
// Protocol contracts do not have an address nullifier in the nullifier tree.
130130
should_check_nullifier = sel * (1 - is_protocol_contract);
131131

132+
// Lookup constant support: Can be removed when we support constants in lookups.
133+
pol commit nullifier_tree_height;
134+
should_check_nullifier * (nullifier_tree_height - constants.NULLIFIER_TREE_HEIGHT) = 0;
135+
136+
// Lookup constant support: Can be removed when we support constants in lookups.
137+
pol commit siloing_separator;
138+
should_check_nullifier * (siloing_separator - constants.DOM_SEP__SILOED_NULLIFIER) = 0;
139+
132140
// Nullifier existence check (deployment nullifier read)
133141
#[DEPLOYMENT_NULLIFIER_READ]
134142
should_check_nullifier {
135143
exists, // does the contract address nullifier exist? gates later lookups....
136144
address, // the deployment nullifier
137145
nullifier_tree_root,
138-
deployer_protocol_contract_address,
139-
sel // 1 (yes silo)
140-
} in nullifier_check.sel {
141-
nullifier_check.exists,
142-
nullifier_check.nullifier,
143-
nullifier_check.root,
144-
nullifier_check.address,
145-
nullifier_check.sel_silo
146+
nullifier_tree_height,
147+
sel, // 1 (yes silo)
148+
siloing_separator,
149+
deployer_protocol_contract_address
150+
} in indexed_tree_check.sel {
151+
indexed_tree_check.exists,
152+
indexed_tree_check.value,
153+
indexed_tree_check.root,
154+
indexed_tree_check.tree_height,
155+
indexed_tree_check.sel_silo,
156+
indexed_tree_check.siloing_separator,
157+
indexed_tree_check.address
146158
};
147159

148160
// For protocol contracts we retrieve the derived address from the protocol contract trace, else use the input address

0 commit comments

Comments
 (0)