Skip to content

Commit

Permalink
refactor: generate public tail hints in noir (#8113)
Browse files Browse the repository at this point in the history
- Generating hints and output for public_kernel_tail in unconstrained
functions.
- Fixing `sort_by_counter` and `assert_deduped_array`.
- Adding new util `assert_combined_sorted_transformed_value_array` to
check the output arrays from public tail that they are merged and sorted
correctly.
  • Loading branch information
LeilaWang authored Aug 23, 2024
1 parent bd6626c commit 576e217
Show file tree
Hide file tree
Showing 45 changed files with 2,333 additions and 1,391 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use dep::types::{
MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL
},
traits::is_empty, transaction::tx_request::TxRequest,
utils::arrays::{array_length, array_to_bounded_vec, sort_by_counters_asc, sort_by_counters_desc}
utils::arrays::{array_length, array_to_bounded_vec, sort_by_counter_asc, sort_by_counter_desc}
};

struct DataSource {
Expand Down Expand Up @@ -101,9 +101,9 @@ impl PrivateKernelCircuitPublicInputsComposer {

pub fn sort_ordered_values(&mut self) {
// Note hashes, nullifiers, note_encrypted_logs_hashes, and encrypted_logs_hashes are sorted in the reset circuit.
self.public_inputs.end.l2_to_l1_msgs.storage = sort_by_counters_asc(self.public_inputs.end.l2_to_l1_msgs.storage);
self.public_inputs.end.unencrypted_logs_hashes.storage = sort_by_counters_asc(self.public_inputs.end.unencrypted_logs_hashes.storage);
self.public_inputs.end.public_call_requests.storage = sort_by_counters_desc(self.public_inputs.end.public_call_requests.storage);
self.public_inputs.end.l2_to_l1_msgs.storage = sort_by_counter_asc(self.public_inputs.end.l2_to_l1_msgs.storage);
self.public_inputs.end.unencrypted_logs_hashes.storage = sort_by_counter_asc(self.public_inputs.end.unencrypted_logs_hashes.storage);
self.public_inputs.end.public_call_requests.storage = sort_by_counter_desc(self.public_inputs.end.public_call_requests.storage);
}

pub fn finish(self) -> PrivateKernelCircuitPublicInputs {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use dep::types::{
MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX,
MAX_NULLIFIERS_PER_TX
},
hash::{mask_encrypted_log_hash, silo_note_hash, silo_nullifier}, utils::arrays::sort_by_counters_asc
hash::{mask_encrypted_log_hash, silo_note_hash, silo_nullifier}, utils::arrays::sort_by_counter_asc
};

struct ResetOutputComposer<
Expand Down Expand Up @@ -99,7 +99,7 @@ impl<
}

fn get_sorted_siloed_note_hashes(self) -> [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX] {
let mut note_hashes = sort_by_counters_asc(self.hints.kept_note_hashes);
let mut note_hashes = sort_by_counter_asc(self.hints.kept_note_hashes);
let first_nullifier = self.previous_kernel.end.nullifiers[0].value();
for i in 0..note_hashes.len() {
note_hashes[i].note_hash.value = silo_note_hash(
Expand All @@ -113,7 +113,7 @@ impl<
}

fn get_sorted_siloed_nullifiers(self) -> [ScopedNullifier; MAX_NULLIFIERS_PER_TX] {
let mut nullifiers = sort_by_counters_asc(self.hints.kept_nullifiers);
let mut nullifiers = sort_by_counter_asc(self.hints.kept_nullifiers);
for i in 0..nullifiers.len() {
nullifiers[i].nullifier.value = silo_nullifier(nullifiers[i]);
nullifiers[i].contract_address = AztecAddress::zero();
Expand All @@ -122,15 +122,15 @@ impl<
}

fn get_sorted_note_encrypted_log_hashes(self) -> [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX] {
let mut log_hashes = sort_by_counters_asc(self.hints.kept_note_encrypted_log_hashes);
let mut log_hashes = sort_by_counter_asc(self.hints.kept_note_encrypted_log_hashes);
for i in 0..log_hashes.len() {
log_hashes[i].note_hash_counter = 0;
}
log_hashes
}

fn get_sorted_masked_encrypted_log_hashes(self) -> [ScopedEncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_TX] {
let mut log_hashes = sort_by_counters_asc(self.previous_kernel.end.encrypted_logs_hashes);
let mut log_hashes = sort_by_counter_asc(self.previous_kernel.end.encrypted_logs_hashes);
for i in 0..log_hashes.len() {
log_hashes[i].contract_address = mask_encrypted_log_hash(log_hashes[i]);
log_hashes[i].log_hash.randomness = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use dep::types::{
MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX,
MAX_NULLIFIERS_PER_TX
},
utils::arrays::{OrderHint, sort_get_order_hints_asc}
utils::arrays::{OrderHint, get_order_hints_asc}
};

struct ResetOutputHints {
Expand Down Expand Up @@ -45,13 +45,13 @@ unconstrained pub fn generate_reset_output_hints<let NUM_TRANSIENT_DATA_INDEX_HI
);

// note_hashes
let sorted_note_hash_indexes = sort_get_order_hints_asc(kept_note_hashes).map(|h: OrderHint| h.sorted_index);
let sorted_note_hash_indexes = get_order_hints_asc(kept_note_hashes).map(|h: OrderHint| h.sorted_index);

// nullifiers
let sorted_nullifier_indexes = sort_get_order_hints_asc(kept_nullifiers).map(|h: OrderHint| h.sorted_index);
let sorted_nullifier_indexes = get_order_hints_asc(kept_nullifiers).map(|h: OrderHint| h.sorted_index);

// note_encrypted_log_hashes
let sorted_note_encrypted_log_hash_indexes = sort_get_order_hints_asc(kept_note_encrypted_log_hashes).map(|h: OrderHint| h.sorted_index);
let sorted_note_encrypted_log_hash_indexes = get_order_hints_asc(kept_note_encrypted_log_hashes).map(|h: OrderHint| h.sorted_index);
let transient_or_propagated_note_hash_indexes_for_logs = get_transient_or_propagated_note_hash_indexes_for_logs(
previous_kernel.end.note_encrypted_logs_hashes,
previous_kernel.end.note_hashes,
Expand All @@ -60,7 +60,7 @@ unconstrained pub fn generate_reset_output_hints<let NUM_TRANSIENT_DATA_INDEX_HI
);

// encrypted_log_hashes
let sorted_encrypted_log_hash_indexes = sort_get_order_hints_asc(previous_kernel.end.encrypted_logs_hashes).map(|h: OrderHint| h.sorted_index);
let sorted_encrypted_log_hash_indexes = get_order_hints_asc(previous_kernel.end.encrypted_logs_hashes).map(|h: OrderHint| h.sorted_index);

ResetOutputHints {
kept_note_hashes,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use dep::types::{
abis::{kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, log_hash::ScopedLogHash},
constants::{MAX_L2_TO_L1_MSGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX},
utils::arrays::{OrderHint, sort_by_counters_asc, sort_get_order_hints_asc}
utils::arrays::{OrderHint, sort_by_counter_asc, get_order_hints_asc}
};

struct TailOutputHints {
Expand All @@ -14,11 +14,11 @@ struct TailOutputHints {

unconstrained pub fn generate_tail_output_hints(previous_kernel: PrivateKernelCircuitPublicInputs) -> TailOutputHints {
// l2_to_l1_msgs
let sorted_l2_to_l1_msg_hints = sort_get_order_hints_asc(previous_kernel.end.l2_to_l1_msgs);
let sorted_l2_to_l1_msg_hints = get_order_hints_asc(previous_kernel.end.l2_to_l1_msgs);

// unencrypted_logs
let sorted_unencrypted_log_hashes = sort_by_counters_asc(previous_kernel.end.unencrypted_logs_hashes);
let sorted_unencrypted_log_hash_hints = sort_get_order_hints_asc(previous_kernel.end.unencrypted_logs_hashes);
let sorted_unencrypted_log_hashes = sort_by_counter_asc(previous_kernel.end.unencrypted_logs_hashes);
let sorted_unencrypted_log_hash_hints = get_order_hints_asc(previous_kernel.end.unencrypted_logs_hashes);

TailOutputHints { sorted_l2_to_l1_msg_hints, sorted_unencrypted_log_hashes, sorted_unencrypted_log_hash_hints }
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use dep::types::{
abis::{kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs},
constants::{MAX_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX},
utils::arrays::{sort_get_split_order_hints_asc, sort_get_split_order_hints_desc, SplitOrderHints}
utils::arrays::{get_split_order_hints_asc, get_split_order_hints_desc, SplitOrderHints}
};

struct TailToPublicOutputHints {
Expand All @@ -17,13 +17,13 @@ unconstrained pub fn generate_tail_to_public_output_hints(previous_kernel: Priva
let split_counter = previous_kernel.min_revertible_side_effect_counter;

// l2_to_l1_msgss
let sorted_l2_to_l1_msg_hints = sort_get_split_order_hints_asc(previous_kernel.end.l2_to_l1_msgs, split_counter);
let sorted_l2_to_l1_msg_hints = get_split_order_hints_asc(previous_kernel.end.l2_to_l1_msgs, split_counter);

// unencrypted_logs
let sorted_unencrypted_log_hash_hints = sort_get_split_order_hints_asc(previous_kernel.end.unencrypted_logs_hashes, split_counter);
let sorted_unencrypted_log_hash_hints = get_split_order_hints_asc(previous_kernel.end.unencrypted_logs_hashes, split_counter);

// public_call_requests
let sorted_public_call_request_hints = sort_get_split_order_hints_desc(previous_kernel.end.public_call_requests, split_counter);
let sorted_public_call_request_hints = get_split_order_hints_desc(previous_kernel.end.public_call_requests, split_counter);

TailToPublicOutputHints { sorted_l2_to_l1_msg_hints, sorted_unencrypted_log_hash_hints, sorted_public_call_request_hints }
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ mod previous_kernel_validator;
mod public_call_data_validator;
mod public_kernel_output_composer;
mod public_tail_output_composer;
mod public_tail_output_validator;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod combine_data;

use crate::components::public_tail_output_composer::combine_data::{combine_data, CombineHints};
use crate::components::public_tail_output_composer::combine_data::combine_data;
use dep::types::{
abis::{kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}},
partial_state_reference::PartialStateReference
Expand All @@ -9,23 +9,20 @@ use dep::types::{
struct PublicTailOutputComposer {
previous_kernel: PublicKernelCircuitPublicInputs,
start_state: PartialStateReference,
combine_hints: CombineHints
}

impl PublicTailOutputComposer {
pub fn new(
previous_kernel: PublicKernelCircuitPublicInputs,
start_state: PartialStateReference,
combine_hints: CombineHints
start_state: PartialStateReference
) -> Self {
PublicTailOutputComposer { previous_kernel, start_state, combine_hints }
PublicTailOutputComposer { previous_kernel, start_state }
}

pub fn finish(self) -> KernelCircuitPublicInputs {
let end = combine_data(
self.previous_kernel.end_non_revertible,
self.previous_kernel.end,
self.combine_hints
self.previous_kernel.end
);

KernelCircuitPublicInputs {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,134 +1,75 @@
use dep::types::{
hash::{compute_tx_logs_hash, compute_tx_note_logs_hash},
abis::{
accumulated_data::{CombinedAccumulatedData, PublicAccumulatedData},
log_hash::{LogHash, ScopedLogHash}, note_hash::ScopedNoteHash, nullifier::Nullifier,
public_data_update_request::PublicDataUpdateRequest, side_effect::Ordered
log_hash::{LogHash, ScopedLogHash}, nullifier::Nullifier
},
constants::{
MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX,
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX,
MAX_ENCRYPTED_LOGS_PER_TX
},
hash::silo_note_hash,
utils::arrays::{array_merge, assert_sorted_array, assert_deduped_array, check_permutation}
constants::MAX_NOTE_HASHES_PER_TX, hash::silo_note_hash,
utils::arrays::{array_merge, dedupe_array, sort_by_counter_asc}
};

struct CombineHints {
sorted_note_hashes: [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX],
sorted_note_hashes_indexes: [u32; MAX_NOTE_HASHES_PER_TX],
sorted_note_encrypted_logs_hashes: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX],
sorted_note_encrypted_logs_hashes_indexes: [u32; MAX_NOTE_ENCRYPTED_LOGS_PER_TX],
sorted_encrypted_logs_hashes: [ScopedLogHash; MAX_ENCRYPTED_LOGS_PER_TX],
sorted_encrypted_logs_hashes_indexes: [u32; MAX_ENCRYPTED_LOGS_PER_TX],
sorted_unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX],
sorted_unencrypted_logs_hashes_indexes: [u32; MAX_UNENCRYPTED_LOGS_PER_TX],
// the public data update requests are sorted by their leaf index AND counter
sorted_public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX],
sorted_public_data_update_requests_indexes: [u32; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX],
// THEN deduplicated based on their leaf slot
deduped_public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX],
deduped_public_data_update_requests_runs: [u32; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX],
}

fn asc_sort_by_counters<T>(a: T, b: T) -> bool where T: Ordered {
a.counter() <= b.counter()
}

pub fn combine_data(
unconstrained pub fn combine_data(
non_revertible: PublicAccumulatedData,
revertible: PublicAccumulatedData,
combine_hints: CombineHints
revertible: PublicAccumulatedData
) -> CombinedAccumulatedData {
let merged_note_hashes = array_merge(non_revertible.note_hashes, revertible.note_hashes);
assert_sorted_array(
merged_note_hashes,
combine_hints.sorted_note_hashes,
combine_hints.sorted_note_hashes_indexes,
asc_sort_by_counters
);

let mut siloed_note_hashes = [0; MAX_NOTE_HASHES_PER_TX];
let sorted_note_hashes = combine_hints.sorted_note_hashes;
let mut note_hashes = [0; MAX_NOTE_HASHES_PER_TX];
let sorted_unsiloed_note_hashes = sort_by_counter_asc(array_merge(non_revertible.note_hashes, revertible.note_hashes));
let tx_hash = non_revertible.nullifiers[0].value;
for i in 0..sorted_note_hashes.len() {
let note_hash = sorted_note_hashes[i];
siloed_note_hashes[i] = if note_hash.counter() == 0 {
// If counter is zero, the note hash was emitted from private and has been siloed in private_kernel_tail_to_public.
for i in 0..sorted_unsiloed_note_hashes.len() {
let note_hash = sorted_unsiloed_note_hashes[i];
note_hashes[i] = if note_hash.counter() == 0 {
// If counter is zero, the note hash is either empty or is emitted from private and has been siloed in private_kernel_tail_to_public.
note_hash.value()
} else {
silo_note_hash(note_hash, tx_hash, i)
};
}

let merged_public_data_update_requests = array_merge(
non_revertible.public_data_update_requests,
revertible.public_data_update_requests
);
let nullifiers = sort_by_counter_asc(array_merge(non_revertible.nullifiers, revertible.nullifiers)).map(|n: Nullifier| n.value);

// Just check a permutation here...
check_permutation(
merged_public_data_update_requests,
combine_hints.sorted_public_data_update_requests,
combine_hints.sorted_public_data_update_requests_indexes
);
// ...because the ordering checks are done here.
assert_deduped_array(
combine_hints.sorted_public_data_update_requests,
combine_hints.deduped_public_data_update_requests,
combine_hints.deduped_public_data_update_requests_runs
);
let l2_to_l1_msgs = sort_by_counter_asc(array_merge(non_revertible.l2_to_l1_msgs, revertible.l2_to_l1_msgs));

let merged_note_encrypted_logs_hashes = array_merge(
non_revertible.note_encrypted_logs_hashes,
revertible.note_encrypted_logs_hashes
);
assert_sorted_array(
merged_note_encrypted_logs_hashes,
combine_hints.sorted_note_encrypted_logs_hashes,
combine_hints.sorted_note_encrypted_logs_hashes_indexes,
asc_sort_by_counters
let public_data_update_requests = dedupe_array(
array_merge(
non_revertible.public_data_update_requests,
revertible.public_data_update_requests
)
);

let merged_encrypted_logs_hashes = array_merge(
non_revertible.encrypted_logs_hashes,
revertible.encrypted_logs_hashes
);
assert_sorted_array(
merged_encrypted_logs_hashes,
combine_hints.sorted_encrypted_logs_hashes,
combine_hints.sorted_encrypted_logs_hashes_indexes,
asc_sort_by_counters
let note_encrypted_logs_hashes = sort_by_counter_asc(
array_merge(
non_revertible.note_encrypted_logs_hashes,
revertible.note_encrypted_logs_hashes
)
);
let note_encrypted_log_preimages_length = note_encrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length);

let merged_unencrypted_logs_hashes = array_merge(
non_revertible.unencrypted_logs_hashes,
revertible.unencrypted_logs_hashes
let encrypted_logs_hashes = sort_by_counter_asc(
array_merge(
non_revertible.encrypted_logs_hashes,
revertible.encrypted_logs_hashes
)
);
assert_sorted_array(
merged_unencrypted_logs_hashes,
combine_hints.sorted_unencrypted_logs_hashes,
combine_hints.sorted_unencrypted_logs_hashes_indexes,
asc_sort_by_counters
let encrypted_log_preimages_length = encrypted_logs_hashes.fold(0, |a, b: ScopedLogHash| a + b.log_hash.length);

let unencrypted_logs_hashes = sort_by_counter_asc(
array_merge(
non_revertible.unencrypted_logs_hashes,
revertible.unencrypted_logs_hashes
)
);
let unencrypted_log_preimages_length = unencrypted_logs_hashes.fold(0, |a, b: ScopedLogHash| a + b.log_hash.length);

let note_encrypted_log_preimages_length = non_revertible.note_encrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length)
+ revertible.note_encrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length);
let encrypted_log_preimages_length = non_revertible.encrypted_logs_hashes.fold(0, |a, b: ScopedLogHash| a + b.log_hash.length)
+ revertible.encrypted_logs_hashes.fold(0, |a, b: ScopedLogHash| a + b.log_hash.length);
let unencrypted_log_preimages_length = non_revertible.unencrypted_logs_hashes.fold(0, |a, b: ScopedLogHash| a + b.log_hash.length)
+ revertible.unencrypted_logs_hashes.fold(0, |a, b: ScopedLogHash| a + b.log_hash.length);
CombinedAccumulatedData {
note_hashes: siloed_note_hashes,
nullifiers: array_merge(non_revertible.nullifiers, revertible.nullifiers).map(|n: Nullifier| n.value),
l2_to_l1_msgs: array_merge(non_revertible.l2_to_l1_msgs, revertible.l2_to_l1_msgs),
note_encrypted_logs_hashes: combine_hints.sorted_note_encrypted_logs_hashes,
encrypted_logs_hashes: combine_hints.sorted_encrypted_logs_hashes,
unencrypted_logs_hashes: combine_hints.sorted_unencrypted_logs_hashes,
note_hashes,
nullifiers,
l2_to_l1_msgs,
note_encrypted_logs_hashes,
encrypted_logs_hashes,
unencrypted_logs_hashes,
note_encrypted_log_preimages_length,
encrypted_log_preimages_length,
unencrypted_log_preimages_length,
public_data_update_requests: combine_hints.deduped_public_data_update_requests,
public_data_update_requests,
gas_used: revertible.gas_used + non_revertible.gas_used
}
}
Loading

0 comments on commit 576e217

Please sign in to comment.