Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: public data reads and writes verification #8296

Merged
merged 18 commits into from
Sep 9, 2024
Merged
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
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use dep::protocol_types::{
constants::PUBLIC_DATA_TREE_HEIGHT, public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage,
utils::arr_copy_slice
};
use dep::protocol_types::{constants::PUBLIC_DATA_TREE_HEIGHT, data::PublicDataTreeLeafPreimage, utils::arr_copy_slice};

global LEAF_PREIMAGE_LENGTH: u32 = 4;
global PUBLIC_DATA_WITNESS: Field = 45;
Expand All @@ -18,7 +15,10 @@ unconstrained fn get_public_data_witness_oracle(
_public_data_tree_index: Field
) -> [Field; PUBLIC_DATA_WITNESS] {}

unconstrained pub fn get_public_data_witness(block_number: u32, public_data_tree_index: Field) -> PublicDataWitness {
unconstrained pub fn get_public_data_witness(
block_number: u32,
public_data_tree_index: Field
) -> PublicDataWitness {
let fields = get_public_data_witness_oracle(block_number, public_data_tree_index);
PublicDataWitness {
index: fields[0],
Expand Down
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)
}
}
Original file line number Diff line number Diff line change
@@ -1,39 +1,22 @@
use crate::components::public_tail_output_composer::generate_output_hints::OutputHints;
use dep::types::{
abis::{
accumulated_data::{CombinedAccumulatedData, PublicAccumulatedData},
log_hash::{LogHash, ScopedLogHash}, nullifier::Nullifier
},
constants::MAX_NOTE_HASHES_PER_TX, hash::silo_note_hash,
utils::arrays::{array_merge, dedupe_array, sort_by_counter_asc}
};

unconstrained pub fn combine_data(
unconstrained pub fn combine_data<let NUM_PUBLIC_DATA_LEAVES: u32>(
non_revertible: PublicAccumulatedData,
revertible: PublicAccumulatedData
revertible: PublicAccumulatedData,
output_hints: OutputHints<NUM_PUBLIC_DATA_LEAVES>
) -> CombinedAccumulatedData {
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_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 nullifiers = sort_by_counter_asc(array_merge(non_revertible.nullifiers, revertible.nullifiers)).map(|n: Nullifier| n.value);

let l2_to_l1_msgs = sort_by_counter_asc(array_merge(non_revertible.l2_to_l1_msgs, revertible.l2_to_l1_msgs));

let public_data_update_requests = dedupe_array(
array_merge(
non_revertible.public_data_update_requests,
revertible.public_data_update_requests
)
);
let public_data_update_requests = dedupe_array(output_hints.public_data_writes);

let note_encrypted_logs_hashes = sort_by_counter_asc(
array_merge(
Expand All @@ -60,7 +43,7 @@ unconstrained pub fn combine_data(
let unencrypted_log_preimages_length = unencrypted_logs_hashes.fold(0, |a, b: ScopedLogHash| a + b.log_hash.length);

CombinedAccumulatedData {
note_hashes,
note_hashes: output_hints.siloed_note_hashes,
nullifiers,
l2_to_l1_msgs,
note_encrypted_logs_hashes,
Expand Down
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
}
}
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)
}
Loading
Loading