Skip to content

Commit

Permalink
Allow all-zero low leaf.
Browse files Browse the repository at this point in the history
  • Loading branch information
LeilaWang committed Apr 12, 2024
1 parent 2d1152a commit fe1bce6
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -236,22 +236,6 @@ mod tests {
);
}

#[test(should_fail_with="Cannot check non membership against empty leaf")]
fn test_reset_non_existent_read_requests_empty_leaf_failed() {
let read_requests = [ReadRequestContext { value: 10, counter: 50, contract_address: AztecAddress::zero() }];
let (non_membership_hints, root) = get_non_membership_hints([0]);
let mut hint = non_membership_hints[0];
hint.low_leaf_preimage = TestLeafPreimage { value: 0, next_value: 0 };
let next_pending_value_indices = [1];
reset_non_existent_read_requests(
read_requests,
[hint],
root,
sorted_pending_values,
next_pending_value_indices
);
}

#[test(should_fail_with="Low leaf does not exist")]
fn test_reset_non_existent_read_requests_invalid_preimage_failed() {
let read_requests = [ReadRequestContext { value: 10, counter: 50, contract_address: AztecAddress::zero() }];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,16 +178,10 @@ impl BaseRollupInputs {
}

fn validate_and_process_public_state(self) -> AppendOnlyTreeSnapshot {
// TODO(#2521) - data read validation should happen against the current state of the tx and not the start state.
// Blocks all interesting usecases that read and write to the same public state in the same tx.
// https://aztecprotocol.slack.com/archives/C02M7VC7TN0/p1695809629015719?thread_ts=1695653252.007339&cid=C02M7VC7TN0

// Process public data reads and public data update requests for left input
// validate_public_data_reads(
// self.start_public_data_tree_root,
// self.kernel_data[0].public_inputs.end.public_data_reads,
// 0,
// self.new_public_data_reads_sibling_paths);
let kernel_state = self.kernel_data.public_inputs.end_state;
if !kernel_state.public_data_tree.eq(AppendOnlyTreeSnapshot::zero()) {
assert(kernel_state.public_data_tree.eq(self.start.public_data_tree), "Mismatch start state");
}

let end_public_data_tree_snapshot = insert_public_data_update_requests(
self.start.public_data_tree,
Expand Down Expand Up @@ -318,43 +312,6 @@ fn insert_public_data_update_requests(
)
}

fn validate_public_data_reads(
tree_root: Field,
public_data_reads: [PublicDataRead; MAX_PUBLIC_DATA_READS_PER_TX],
public_data_reads_preimages: [PublicDataTreeLeafPreimage; MAX_PUBLIC_DATA_READS_PER_TX],
public_data_reads_witnesses: [PublicDataMembershipWitness; MAX_PUBLIC_DATA_READS_PER_TX]
) {
for i in 0..MAX_PUBLIC_DATA_READS_PER_TX {
let read = public_data_reads[i];
let low_preimage = public_data_reads_preimages[i];
let witness = public_data_reads_witnesses[i];

let is_low_empty = low_preimage.is_empty();
let is_exact = low_preimage.slot == read.leaf_slot;

let is_less_than_slot = full_field_less_than(low_preimage.slot, read.leaf_slot);
let is_next_greater_than = full_field_less_than(read.leaf_slot, low_preimage.next_slot);
let is_in_range = is_less_than_slot
& (is_next_greater_than | ((low_preimage.next_index == 0) & (low_preimage.next_slot == 0)));

if (!read.is_empty()) {
assert(!is_low_empty, "public data read is not empty but low preimage is empty");
if is_in_range {
assert_eq(read.value, 0, "low leaf for public data read is in range but value is not zero");
} else {
assert(is_exact, "low leaf for public data read is invalid");
assert_eq(read.value, low_preimage.value, "low leaf for public data has different value");
}
assert_check_membership(
low_preimage.hash(),
witness.leaf_index,
witness.sibling_path,
tree_root
);
}
}
}

#[test]
fn consistent_not_hash_subtree_width() {
assert_eq(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ pub fn assert_check_valid_low_leaf<LEAF_PREIMAGE>(
) where LEAF_PREIMAGE: IndexedTreeLeafPreimage {
let low_key = low_leaf_preimage.get_key();
let next_key = low_leaf_preimage.get_next_key();
let is_empty_leaf = (low_key == 0) & (next_key == 0);

assert(!is_empty_leaf, "Cannot check non membership against empty leaf");
assert(low_key.lt(key), "Key is not greater than the low leaf");
assert(key.lt(next_key) | (next_key == 0), "Key is not less than the next leaf");
}
Expand Down Expand Up @@ -47,10 +45,14 @@ mod tests {
assert_check_valid_low_leaf(key, leaf);
}

#[test(should_fail_with="Cannot check non membership against empty leaf")]
fn test_assert_check_valid_low_leaf_failed_empty_leaf() {
let empty_leaf = TestLeafPreimage { value: 0, next_value: 0 };
assert_check_valid_low_leaf(0, empty_leaf);
#[test]
fn test_assert_check_empty_low_leaf() {
// An all-zero low leaf should be valid. It could be used as the first dummy leaf in a tree.
// It's not possible to prove against an empty leaf at an uninitialized index.
// The membership check will fail because the leaf value hash(0, 0) is not 0.
let key = 12;
let leaf = TestLeafPreimage { value: 0, next_value: 0 };
assert_check_valid_low_leaf(key, leaf);
}

#[test(should_fail_with="Key is not greater than the low leaf")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,6 @@ mod tests {
assert_check_non_membership_at_index(1, 45);
}

#[test(should_fail_with="Cannot check non membership against empty leaf")]
fn test_assert_check_non_membership_failed_empty_leaf() {
assert_check_non_membership_at_index(4, 25);
}

#[test(should_fail_with="Key is not greater than the low leaf")]
fn test_assert_check_non_membership_failed_wrong_low_leaf() {
assert_check_non_membership_at_index(3, 25);
Expand Down Expand Up @@ -292,11 +287,6 @@ mod tests {
conditionally_assert_check_membership_at_index(true, 1, leaf_preimages[1].get_key() + 1);
}

#[test(should_fail_with="Cannot check non membership against empty leaf")]
fn test_conditionally_assert_check_membership_failed_not_exists_empty_leaf() {
conditionally_assert_check_membership_at_index(false, 4, 1);
}

#[test(should_fail_with="Key is not greater than the low leaf")]
fn test_conditionally_assert_check_membership_failed_not_exists_wrong_low_leaf() {
conditionally_assert_check_membership_at_index(false, 3, 25);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import {
import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash';
import { fr, makeAztecAddress, makePublicCallRequest, makeSelector } from '@aztec/circuits.js/testing';
import { arrayNonEmptyLength, padArrayEnd } from '@aztec/foundation/collection';
import { pedersenHash } from '@aztec/foundation/crypto';
import { openTmpStore } from '@aztec/kv-store/utils';
import { type AppendOnlyTree, Pedersen, StandardTree, newTree } from '@aztec/merkle-tree';
import { type PublicExecution, type PublicExecutionResult, type PublicExecutor, WASMSimulator } from '@aztec/simulator';
Expand Down Expand Up @@ -176,12 +175,8 @@ describe('public_processor', () => {
'PublicData',
Fr,
PUBLIC_DATA_TREE_HEIGHT,
1, // Add a default low leaf for the public data hints to be proved against.
);
// Add a default low leaf for the public data hints to be proved against.
const defaultLeaves = [new PublicDataTreeLeafPreimage(new Fr(1), new Fr(0), new Fr(0), 0n)].map(l =>
pedersenHash(l.toHashInputs()),
);
await publicDataTree.appendLeaves(defaultLeaves);
});

beforeEach(() => {
Expand All @@ -195,13 +190,13 @@ describe('public_processor', () => {
header.state.l1ToL2MessageTree,
new PartialStateReference(header.state.partial.noteHashTree, header.state.partial.nullifierTree, snap),
);
// Clone the whole state because somewhere down the line something is changing the public data root in header.
// Clone the whole state because somewhere down the line (AbstractPhaseManager) the public data root is modified in the referenced header directly :/
header.state = StateReference.fromBuffer(stateReference.toBuffer());

db.getStateReference.mockResolvedValue(stateReference);
db.getSiblingPath.mockResolvedValue(publicDataTree.getSiblingPath(0n, false));
db.getPreviousValueIndex.mockResolvedValue({ index: 0n, alreadyPresent: true });
db.getLeafPreimage.mockResolvedValue(new PublicDataTreeLeafPreimage(new Fr(1), new Fr(0), new Fr(0), 0n));
db.getLeafPreimage.mockResolvedValue(new PublicDataTreeLeafPreimage(new Fr(0), new Fr(0), new Fr(0), 0n));

publicKernel = new RealPublicKernelCircuitSimulator(new WASMSimulator());
processor = new PublicProcessor(
Expand Down

0 comments on commit fe1bce6

Please sign in to comment.