-
Notifications
You must be signed in to change notification settings - Fork 234
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: public data reads and writes verification (#8296)
- Add counter to `PublicDataUpdateRequest` so that we can check the ordering of the reads vs writes and verify that the reads are reading the correct value, either in the tree or a newly updated value. - Improve the algorithm for squashing writes. - Build hints in noir.
- Loading branch information
Showing
84 changed files
with
2,534 additions
and
2,784 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 20 additions & 10 deletions
30
...-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer.nr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,47 @@ | ||
mod combine_data; | ||
mod generate_output_hints; | ||
mod generate_overridable_public_data_writes; | ||
mod generate_public_data_leaves; | ||
|
||
use crate::components::public_tail_output_composer::combine_data::combine_data; | ||
use generate_output_hints::{LinkedIndexHint, OutputHints, SiloedNoteHashHint}; | ||
|
||
use crate::components::public_tail_output_composer::{combine_data::combine_data, generate_output_hints::generate_output_hints}; | ||
use dep::types::{ | ||
abis::{kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}}, | ||
partial_state_reference::PartialStateReference | ||
data::PublicDataLeafHint, partial_state_reference::PartialStateReference | ||
}; | ||
|
||
struct PublicTailOutputComposer { | ||
struct PublicTailOutputComposer<let NUM_PUBLIC_DATA_LEAVES: u32> { | ||
previous_kernel: PublicKernelCircuitPublicInputs, | ||
start_state: PartialStateReference, | ||
public_data_leaf_hints: [PublicDataLeafHint; NUM_PUBLIC_DATA_LEAVES], | ||
} | ||
|
||
impl PublicTailOutputComposer { | ||
impl<let NUM_PUBLIC_DATA_LEAVES: u32> PublicTailOutputComposer<NUM_PUBLIC_DATA_LEAVES> { | ||
pub fn new( | ||
previous_kernel: PublicKernelCircuitPublicInputs, | ||
start_state: PartialStateReference | ||
start_state: PartialStateReference, | ||
public_data_leaf_hints: [PublicDataLeafHint; NUM_PUBLIC_DATA_LEAVES] | ||
) -> Self { | ||
PublicTailOutputComposer { previous_kernel, start_state } | ||
PublicTailOutputComposer { previous_kernel, start_state, public_data_leaf_hints } | ||
} | ||
|
||
pub fn finish(self) -> KernelCircuitPublicInputs { | ||
pub fn finish(self) -> (KernelCircuitPublicInputs, OutputHints<NUM_PUBLIC_DATA_LEAVES>) { | ||
let output_hints = generate_output_hints(self.previous_kernel, self.public_data_leaf_hints); | ||
|
||
let end = combine_data( | ||
self.previous_kernel.end_non_revertible, | ||
self.previous_kernel.end | ||
self.previous_kernel.end, | ||
output_hints | ||
); | ||
|
||
KernelCircuitPublicInputs { | ||
(KernelCircuitPublicInputs { | ||
rollup_validation_requests: self.previous_kernel.validation_requests.for_rollup, | ||
end, | ||
constants: self.previous_kernel.constants, | ||
start_state: self.start_state, | ||
revert_code: self.previous_kernel.revert_code, | ||
fee_payer: self.previous_kernel.fee_payer | ||
} | ||
}, output_hints) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
...tes/public-kernel-lib/src/components/public_tail_output_composer/generate_output_hints.nr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
use crate::components::public_tail_output_composer::{ | ||
generate_overridable_public_data_writes::{generate_overridable_public_data_writes, LinkedIndexHint}, | ||
generate_public_data_leaves::generate_public_data_leaves | ||
}; | ||
use dep::types::{ | ||
abis::{ | ||
kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, | ||
public_data_write::OverridablePublicDataWrite | ||
}, | ||
constants::{ | ||
MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, | ||
MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, | ||
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX | ||
}, | ||
data::{OverridablePublicDataTreeLeaf, PublicDataLeafHint}, hash::silo_note_hash, traits::Empty, | ||
utils::arrays::{array_merge, CombinedOrderHint, get_combined_order_hints_asc, sort_by_counter_asc, SortedResult} | ||
}; | ||
|
||
struct SiloedNoteHashHint { | ||
siloed_note_hash: Field, | ||
index: u32, | ||
} | ||
|
||
impl Empty for SiloedNoteHashHint { | ||
fn empty() -> Self { | ||
SiloedNoteHashHint { siloed_note_hash: 0, index: 0 } | ||
} | ||
} | ||
|
||
impl Eq for SiloedNoteHashHint { | ||
fn eq(self, other: Self) -> bool { | ||
(self.siloed_note_hash == other.siloed_note_hash) & (self.index == other.index) | ||
} | ||
} | ||
|
||
struct OutputHints<let NUM_PUBLIC_DATA_LEAVES: u32> { | ||
siloed_note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], | ||
siloed_note_hash_hints: [SiloedNoteHashHint; MAX_NOTE_HASHES_PER_TX], | ||
sorted_note_hash_hints: [CombinedOrderHint; MAX_NOTE_HASHES_PER_TX], | ||
sorted_nullifier_hints: [CombinedOrderHint; MAX_NULLIFIERS_PER_TX], | ||
sorted_l2_to_l1_msg_hints: [CombinedOrderHint; MAX_L2_TO_L1_MSGS_PER_TX], | ||
sorted_note_encrypted_log_hash_hints: [CombinedOrderHint; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], | ||
sorted_encrypted_log_hash_hints: [CombinedOrderHint; MAX_ENCRYPTED_LOGS_PER_TX], | ||
sorted_unencrypted_log_hash_hints: [CombinedOrderHint; MAX_UNENCRYPTED_LOGS_PER_TX], | ||
public_data_writes: [OverridablePublicDataWrite; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], | ||
public_data_leaves: [OverridablePublicDataTreeLeaf; NUM_PUBLIC_DATA_LEAVES], | ||
unique_slot_index_hints: SortedResult<Field, NUM_PUBLIC_DATA_LEAVES>, | ||
public_data_linked_index_hints: [LinkedIndexHint; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], | ||
} | ||
|
||
unconstrained pub fn generate_output_hints<let NUM_PUBLIC_DATA_LEAVES: u32>( | ||
previous_kernel: PublicKernelCircuitPublicInputs, | ||
public_data_leaf_hints: [PublicDataLeafHint; NUM_PUBLIC_DATA_LEAVES] | ||
) -> OutputHints<NUM_PUBLIC_DATA_LEAVES> { | ||
let non_revertible = previous_kernel.end_non_revertible; | ||
let revertible = previous_kernel.end; | ||
|
||
// Note hashes. | ||
let mut siloed_note_hashes = [0; MAX_NOTE_HASHES_PER_TX]; | ||
let mut siloed_note_hash_hints = [SiloedNoteHashHint::empty(); 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_unsiloed_note_hashes.len() { | ||
let note_hash = sorted_unsiloed_note_hashes[i]; | ||
let siloed_note_hash = 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) | ||
}; | ||
siloed_note_hashes[i] = siloed_note_hash; | ||
if siloed_note_hash != 0 { | ||
siloed_note_hash_hints[i] = SiloedNoteHashHint { siloed_note_hash, index: i }; | ||
} | ||
} | ||
|
||
// Public data. | ||
let combined_writes = array_merge( | ||
previous_kernel.end_non_revertible.public_data_update_requests, | ||
previous_kernel.end.public_data_update_requests | ||
); | ||
let (public_data_leaves, unique_slot_index_hints) = generate_public_data_leaves( | ||
previous_kernel.validation_requests.public_data_reads, | ||
combined_writes, | ||
public_data_leaf_hints | ||
); | ||
let (public_data_writes, public_data_linked_index_hints) = generate_overridable_public_data_writes(combined_writes, public_data_leaves); | ||
|
||
OutputHints { | ||
siloed_note_hashes, | ||
siloed_note_hash_hints, | ||
sorted_note_hash_hints: get_combined_order_hints_asc(non_revertible.note_hashes, revertible.note_hashes), | ||
sorted_nullifier_hints: get_combined_order_hints_asc(non_revertible.nullifiers, revertible.nullifiers), | ||
sorted_l2_to_l1_msg_hints: get_combined_order_hints_asc(non_revertible.l2_to_l1_msgs, revertible.l2_to_l1_msgs), | ||
sorted_note_encrypted_log_hash_hints: get_combined_order_hints_asc( | ||
non_revertible.note_encrypted_logs_hashes, | ||
revertible.note_encrypted_logs_hashes | ||
), | ||
sorted_encrypted_log_hash_hints: get_combined_order_hints_asc( | ||
non_revertible.encrypted_logs_hashes, | ||
revertible.encrypted_logs_hashes | ||
), | ||
sorted_unencrypted_log_hash_hints: get_combined_order_hints_asc( | ||
non_revertible.unencrypted_logs_hashes, | ||
revertible.unencrypted_logs_hashes | ||
), | ||
public_data_writes, | ||
public_data_leaves, | ||
unique_slot_index_hints, | ||
public_data_linked_index_hints | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
...lib/src/components/public_tail_output_composer/generate_overridable_public_data_writes.nr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
use dep::types::{ | ||
abis::{public_data_update_request::PublicDataUpdateRequest, public_data_write::OverridablePublicDataWrite}, | ||
data::OverridablePublicDataTreeLeaf, traits::Empty, utils::arrays::{array_length, find_index_hint} | ||
}; | ||
|
||
struct LinkedIndexHint { | ||
is_first_write: bool, | ||
prev_index: u32, | ||
} | ||
|
||
impl Empty for LinkedIndexHint { | ||
fn empty() -> Self { | ||
LinkedIndexHint { is_first_write: false, prev_index: 0 } | ||
} | ||
} | ||
|
||
unconstrained pub fn generate_overridable_public_data_writes<let NUM_WRITES: u32, let NUM_LEAVES: u32>( | ||
public_data_writes: [PublicDataUpdateRequest; NUM_WRITES], | ||
public_data_leaves: [OverridablePublicDataTreeLeaf; NUM_LEAVES] | ||
) -> ([OverridablePublicDataWrite; NUM_WRITES], [LinkedIndexHint; NUM_WRITES]) { | ||
let mut overridable_public_data_writes = [OverridablePublicDataWrite::empty(); NUM_WRITES]; | ||
let mut hints = [LinkedIndexHint::empty(); NUM_WRITES]; | ||
|
||
let writes_len = array_length(public_data_writes); | ||
for i in 0..writes_len { | ||
let write = public_data_writes[i]; | ||
let mut override_counter = 0; | ||
let mut is_first_write = false; | ||
let mut prev_index = 0; | ||
let mut prev_counter = 0; | ||
|
||
for j in 0..writes_len { | ||
let other = public_data_writes[j]; | ||
if (j != i) & (other.leaf_slot == write.leaf_slot) { | ||
if other.counter > write.counter { | ||
if (override_counter == 0) | (other.counter < override_counter) { | ||
override_counter = other.counter; | ||
} | ||
} else if other.counter < write.counter { | ||
if other.counter > prev_counter { | ||
prev_counter = other.counter; | ||
prev_index = j; | ||
} | ||
} | ||
} | ||
} | ||
|
||
if prev_counter == 0 { | ||
is_first_write = true; | ||
prev_index = find_index_hint(public_data_leaves, |leaf: OverridablePublicDataTreeLeaf| leaf.leaf.slot == write.leaf_slot); | ||
} | ||
|
||
overridable_public_data_writes[i] = OverridablePublicDataWrite { write, override_counter }; | ||
hints[i] = LinkedIndexHint { is_first_write, prev_index }; | ||
} | ||
|
||
(overridable_public_data_writes, hints) | ||
} |
Oops, something went wrong.