Skip to content

Commit

Permalink
feat: Nullifier read requests in public kernel (#4910)
Browse files Browse the repository at this point in the history
Verifying nullifier read requests in tail public kernel circuit.
  • Loading branch information
LeilaWang authored Mar 7, 2024
1 parent fed729d commit 0e44247
Show file tree
Hide file tree
Showing 60 changed files with 1,297 additions and 242 deletions.
2 changes: 1 addition & 1 deletion l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ library Constants {
uint256 internal constant PARTIAL_STATE_REFERENCE_LENGTH = 8;
uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 223;
uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 218;
uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 195;
uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 199;
uint256 internal constant STATE_REFERENCE_LENGTH = 10;
uint256 internal constant TX_CONTEXT_DATA_LENGTH = 11;
uint256 internal constant TX_REQUEST_LENGTH = 17;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ impl PrivateContext {
call_context: reader.read_struct(CallContext::deserialize),
args_hash: reader.read(),
return_values: [0; RETURN_VALUES_LENGTH],
nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],
contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],
contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],
public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],
Expand Down
15 changes: 11 additions & 4 deletions noir-projects/aztec-nr/aztec/src/context/public_context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ use dep::protocol_types::{
global_variables::GlobalVariables, function_selector::FunctionSelector,
private_circuit_public_inputs::PrivateCircuitPublicInputs,
public_call_stack_item::PublicCallStackItem,
public_circuit_public_inputs::PublicCircuitPublicInputs,
public_circuit_public_inputs::PublicCircuitPublicInputs, read_request::ReadRequest,
side_effect::{SideEffect, SideEffectLinkedToNoteHash}
},
address::{AztecAddress, EthAddress},
constants::{
MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,
MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,
NUM_FIELDS_PER_SHA256, RETURN_VALUES_LENGTH
MAX_NULLIFIER_READ_REQUESTS_PER_CALL, NUM_FIELDS_PER_SHA256, RETURN_VALUES_LENGTH
},
contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},
hash::hash_args, header::Header, messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader
Expand All @@ -28,6 +28,7 @@ struct PublicContext {
args_hash : Field,
return_values : BoundedVec<Field, RETURN_VALUES_LENGTH>,

nullifier_read_requests: BoundedVec<ReadRequest, MAX_NULLIFIER_READ_REQUESTS_PER_CALL>,
contract_storage_update_requests: BoundedVec<StorageUpdateRequest, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL>,
contract_storage_reads: BoundedVec<StorageRead, MAX_PUBLIC_DATA_READS_PER_CALL>,
public_call_stack_hashes: BoundedVec<Field, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL>,
Expand Down Expand Up @@ -95,13 +96,12 @@ impl ContextInterface for PublicContext {

impl PublicContext {
pub fn new(inputs: PublicContextInputs, args_hash: Field) -> PublicContext {
let empty_storage_read = StorageRead::empty();
let empty_storage_update = StorageUpdateRequest::empty();
PublicContext {
inputs,
side_effect_counter: inputs.call_context.start_side_effect_counter,
args_hash,
return_values: BoundedVec::new(),
nullifier_read_requests: BoundedVec::new(),
contract_storage_update_requests: BoundedVec::new(),
contract_storage_reads: BoundedVec::new(),
public_call_stack_hashes: BoundedVec::new(),
Expand Down Expand Up @@ -147,6 +147,7 @@ impl PublicContext {
let pub_circuit_pub_inputs = PublicCircuitPublicInputs {
call_context: self.inputs.call_context, // Done
args_hash: self.args_hash, // Done
nullifier_read_requests: self.nullifier_read_requests.storage,
contract_storage_update_requests: self.contract_storage_update_requests.storage,
contract_storage_reads: self.contract_storage_reads.storage,
return_values: self.return_values.storage,
Expand All @@ -163,6 +164,12 @@ impl PublicContext {
pub_circuit_pub_inputs
}

pub fn push_nullifier_read_request(&mut self, nullifier: Field) {
let request = ReadRequest { value: nullifier, counter: self.side_effect_counter };
self.nullifier_read_requests.push(request);
self.side_effect_counter = self.side_effect_counter + 1;
}

pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {
let message = L2ToL1Message { recipient, content };
self.new_l2_to_l1_msgs.push(message);
Expand Down
2 changes: 2 additions & 0 deletions noir-projects/noir-protocol-circuits/Nargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ members = [
"crates/public-kernel-app-logic-simulated",
"crates/public-kernel-teardown",
"crates/public-kernel-teardown-simulated",
"crates/public-kernel-tail",
"crates/public-kernel-tail-simulated",
"crates/rollup-lib",
"crates/rollup-merge",
"crates/rollup-base",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ compiler_version = ">=0.18.0"

[dependencies]
types = { path = "../types" }
reset_kernel_lib = { path = "../reset-kernel-lib" }
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,3 @@ use private_kernel_tail::PrivateKernelTailCircuitPrivateInputs;

// TODO: rename to be precise as to what its common to.
mod common;
mod read_request_reset;
mod nullifier_read_request_reset;
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use crate::{
common, nullifier_read_request_reset::NullifierReadRequestResetHints,
read_request_reset::reset_read_requests
};
use crate::common;
use dep::std::{cmp::Eq, option::Option, unsafe};
use dep::reset_kernel_lib::{NullifierReadRequestResetHints, reset_read_requests};
use dep::types::{
abis::{
call_request::CallRequest, nullifier_key_validation_request::NullifierKeyValidationRequestContext,
Expand Down Expand Up @@ -109,11 +107,7 @@ impl PrivateKernelTailCircuitPrivateInputs {
public_inputs.end.note_hash_read_requests = BoundedVec::new();
}

fn assert_sorted_counters<T, N>(
original: [T; N],
sorted: [T; N],
indexes: [u64; N]
) where T: Eq + Ordered + Empty {
fn assert_sorted_counters<T, N>(original: [T; N], sorted: [T; N], indexes: [u64; N]) where T: Eq + Ordered + Empty {
let mut prev_was_empty = false;

for i in 0..N {
Expand Down Expand Up @@ -260,9 +254,9 @@ impl PrivateKernelTailCircuitPrivateInputs {

mod tests {
use dep::std::{cmp::Eq, unsafe};
use crate::{
nullifier_read_request_reset::NullifierReadRequestResetHintsBuilder,
private_kernel_tail::PrivateKernelTailCircuitPrivateInputs,
use crate::{private_kernel_tail::PrivateKernelTailCircuitPrivateInputs};
use dep::reset_kernel_lib::{
NullifierReadRequestResetHintsBuilder,
read_request_reset::{PendingReadHint, ReadRequestState, ReadRequestStatus}
};
use dep::types::constants::{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ compiler_version = ">=0.18.0"

[dependencies]
types = { path = "../types" }
reset_kernel_lib = { path = "../reset-kernel-lib" }
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
use dep::types::{
abis::{
call_request::CallRequest, public_call_stack_item::PublicCallStackItem,
accumulated_data::{CombinedAccumulatedData, CombinedAccumulatedDataBuilder},
kernel_circuit_public_inputs::PublicKernelCircuitPublicInputsBuilder,
new_contract_data::NewContractData, kernel_data::{PrivateKernelTailData, PublicKernelData},
public_call_data::PublicCallData, public_circuit_public_inputs::PublicCircuitPublicInputs,
public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest,
public_call_data::PublicCallData, public_data_read::PublicDataRead,
public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequestContext,
side_effect::{SideEffect, SideEffectLinkedToNoteHash}
},
address::AztecAddress,
contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},
constants::{
MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,
MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
MAX_PUBLIC_DATA_READS_PER_CALL, NUM_FIELDS_PER_SHA256, MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX,
MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_PUBLIC_DATA_READS_PER_CALL, NUM_FIELDS_PER_SHA256,
MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX
},
hash::{silo_note_hash, silo_nullifier, compute_l2_to_l1_hash, accumulate_sha256},
Expand Down Expand Up @@ -47,44 +46,56 @@ pub fn initialize_reverted_flag(
circuit_outputs.reverted = previous_kernel.public_inputs.reverted | public_call.call_stack_item.public_inputs.reverted;
}

pub fn initialize_end_values(
// Initialises the circuit outputs with the end state of the previous iteration.
// Skips data that will be checked and cleared in the tail circuit.
pub fn initialize_emitted_end_values(
previous_kernel: PublicKernelData,
circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder
) {
// Initialises the circuit outputs with the end state of the previous iteration
circuit_outputs.constants = previous_kernel.public_inputs.constants;

// Ensure the arrays are the same as previously, before we start pushing more data onto them in other
// functions within this circuit:
let start = previous_kernel.public_inputs.end;

if circuit_outputs.reverted == false {
let start = previous_kernel.public_inputs.end;
circuit_outputs.end.new_note_hashes = array_to_bounded_vec(start.new_note_hashes);
circuit_outputs.end.new_nullifiers = array_to_bounded_vec(start.new_nullifiers);

circuit_outputs.end.private_call_stack = array_to_bounded_vec(start.private_call_stack);
circuit_outputs.end.public_call_stack = array_to_bounded_vec(start.public_call_stack);
circuit_outputs.end.new_l2_to_l1_msgs = array_to_bounded_vec(start.new_l2_to_l1_msgs);

circuit_outputs.end.public_data_update_requests = array_to_bounded_vec(start.public_data_update_requests);
// TODO - should be propagated only in initialize_end_values() and clear them in the tail circuit.
circuit_outputs.end.public_data_reads = array_to_bounded_vec(start.public_data_reads);

// Public kernel does not modify encrypted logs values --> we just copy them to output
circuit_outputs.end.unencrypted_logs_hash = start.unencrypted_logs_hash;
circuit_outputs.end.unencrypted_log_preimages_length = start.unencrypted_log_preimages_length;
circuit_outputs.end.encrypted_logs_hash = start.encrypted_logs_hash;
circuit_outputs.end.encrypted_log_preimages_length = start.encrypted_log_preimages_length;

circuit_outputs.end.new_contracts = array_to_bounded_vec(previous_kernel.public_inputs.end.new_contracts);
}

let start_non_revertible = previous_kernel.public_inputs.end_non_revertible;
circuit_outputs.end_non_revertible.new_note_hashes = array_to_bounded_vec(start_non_revertible.new_note_hashes);
circuit_outputs.end_non_revertible.new_nullifiers = array_to_bounded_vec(start_non_revertible.new_nullifiers);
circuit_outputs.end_non_revertible.public_call_stack = array_to_bounded_vec(start_non_revertible.public_call_stack);

circuit_outputs.end_non_revertible.public_data_update_requests = array_to_bounded_vec(start_non_revertible.public_data_update_requests);
circuit_outputs.end_non_revertible.public_data_reads = array_to_bounded_vec(start_non_revertible.public_data_reads);
}

// Initialises the circuit outputs with the end state of the previous iteration.
// Includes data that will be checked and cleared in the tail circuit.
pub fn initialize_end_values(
previous_kernel: PublicKernelData,
circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder
) {
initialize_emitted_end_values(previous_kernel, circuit_outputs);

if circuit_outputs.reverted == false {
let start = previous_kernel.public_inputs.end;
// circuit_outputs.end.private_call_stack = array_to_bounded_vec(start.private_call_stack); // This is enforced in the private tail to always be empty.
circuit_outputs.end.public_call_stack = array_to_bounded_vec(start.public_call_stack);
circuit_outputs.end.nullifier_read_requests = array_to_bounded_vec(start.nullifier_read_requests);
}

let start_non_revertible = previous_kernel.public_inputs.end_non_revertible;
circuit_outputs.end_non_revertible.public_call_stack = array_to_bounded_vec(start_non_revertible.public_call_stack);
circuit_outputs.end_non_revertible.nullifier_read_requests = array_to_bounded_vec(start_non_revertible.nullifier_read_requests);
}

fn perform_static_call_checks(public_call: PublicCallData) {
let public_inputs = public_call.call_stack_item.public_inputs;
if public_inputs.call_context.is_static_call {
Expand Down Expand Up @@ -154,6 +165,7 @@ pub fn update_public_end_non_revertible_values(
validate_call_requests(public_call_requests, hashes, public_call);
circuit_outputs.end_non_revertible.public_call_stack.extend_from_bounded_vec(public_call_requests);

propagate_nullifier_read_requests_non_revertible(public_call, circuit_outputs);
propagate_new_nullifiers_non_revertible(public_call, circuit_outputs);
propagate_new_note_hashes_non_revertible(public_call, circuit_outputs);
propagate_valid_non_revertible_public_data_update_requests(public_call, circuit_outputs);
Expand All @@ -174,6 +186,7 @@ pub fn update_public_end_values(public_call: PublicCallData, circuit_outputs: &m
validate_call_requests(public_call_requests, hashes, public_call);
circuit_outputs.end.public_call_stack.extend_from_bounded_vec(public_call_requests);

propagate_nullifier_read_requests_revertible(public_call, circuit_outputs);
propagate_new_nullifiers(public_call, circuit_outputs);
propagate_new_note_hashes(public_call, circuit_outputs);

Expand All @@ -184,6 +197,38 @@ pub fn update_public_end_values(public_call: PublicCallData, circuit_outputs: &m
propagate_valid_public_data_reads(public_call, circuit_outputs);
}

fn propagate_nullifier_read_requests_non_revertible<T>(
public_call: PublicCallData,
circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder
) {
let public_call_public_inputs = public_call.call_stack_item.public_inputs;
let nullifier_read_requests = public_call_public_inputs.nullifier_read_requests;
let storage_contract_address = public_call_public_inputs.call_context.storage_contract_address;

for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL {
let request = nullifier_read_requests[i];
if !is_empty(request) {
circuit_outputs.end_non_revertible.nullifier_read_requests.push(request.to_context(storage_contract_address));
}
}
}

fn propagate_nullifier_read_requests_revertible<T>(
public_call: PublicCallData,
circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder
) {
let public_call_public_inputs = public_call.call_stack_item.public_inputs;
let nullifier_read_requests = public_call_public_inputs.nullifier_read_requests;
let storage_contract_address = public_call_public_inputs.call_context.storage_contract_address;

for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL {
let request = nullifier_read_requests[i];
if !is_empty(request) {
circuit_outputs.end.nullifier_read_requests.push(request.to_context(storage_contract_address));
}
}
}

fn propagate_valid_public_data_update_requests(
public_call: PublicCallData,
circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ mod utils;
mod public_kernel_setup;
mod public_kernel_app_logic;
mod public_kernel_teardown;
mod public_kernel_tail;

use public_kernel_setup::PublicKernelSetupCircuitPrivateInputs;
use public_kernel_app_logic::PublicKernelAppLogicCircuitPrivateInputs;
use public_kernel_teardown::PublicKernelTeardownCircuitPrivateInputs;
use public_kernel_tail::PublicKernelTailCircuitPrivateInputs;
Loading

0 comments on commit 0e44247

Please sign in to comment.