Skip to content

Commit

Permalink
feat: Extend Historical Access APIs AztecProtocol#4179 (AztecProtocol…
Browse files Browse the repository at this point in the history
  • Loading branch information
sklppy88 committed Feb 5, 2024
1 parent 137c1b0 commit 37ecf2c
Show file tree
Hide file tree
Showing 9 changed files with 349 additions and 149 deletions.
31 changes: 28 additions & 3 deletions yarn-project/aztec-nr/aztec/src/history/contract_inclusion.nr
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@ pub fn prove_contract_inclusion(
contract_class_id: ContractClassId,
initialization_hash: Field,
portal_contract_address: EthAddress,
block_number: u32, // The block at which we'll prove that the public value exists
context: PrivateContext
) -> AztecAddress {
// 1) Get block header from oracle and ensure that the block is included in the archive.
// let block_header = context.get_header.at(block_number);
// 1) Get block header from context
// let block_header = context.historical_header;

// 2) Compute the contract address
let contract_address = AztecAddress::compute_from_public_key(
Expand Down Expand Up @@ -64,3 +63,29 @@ pub fn prove_contract_inclusion(

contract_address
}

pub fn prove_contract_inclusion_at(
public_key: GrumpkinPoint,
contract_address_salt: Field,
contract_class_id: ContractClassId,
initialization_hash: Field,
portal_contract_address: EthAddress,
block_number: u32,
context: PrivateContext
) -> AztecAddress {
// 1) Get block header from oracle and ensure that the block is included in the archive.
let header = context.get_header_at(block_number);

// 2) Compute the contract address
let contract_address = AztecAddress::compute_from_public_key(
public_key,
contract_class_id,
contract_address_salt,
initialization_hash,
portal_contract_address
);

// TODO(@spalladino): See above func to impl

contract_address
}
32 changes: 15 additions & 17 deletions yarn-project/aztec-nr/aztec/src/history/note_inclusion.nr
Original file line number Diff line number Diff line change
@@ -1,40 +1,38 @@
use dep::std::merkle::compute_merkle_root;
use dep::protocol_types::header::Header;

use crate::{
context::PrivateContext,
note::{
utils::compute_note_hash_for_consumption,
note_header::NoteHeader,
note_interface::NoteInterface,
},
oracle::get_membership_witness::get_note_hash_membership_witness,
};

pub fn prove_note_commitment_inclusion(
note_commitment: Field,
block_number: u32, // The block at which we'll prove that the note exists
context: PrivateContext
) {
// 1) Get block header from oracle and ensure that the block is included in the archive.
let header = context.get_header_at(block_number);
fn _note_inclusion<Note, N>(note: Note, header: Header) where Note: NoteInterface<N> {
// 1) Compute note_hash
let note_hash = compute_note_hash_for_consumption(note);

// 2) Get the membership witness of the note in the note hash tree
let witness = get_note_hash_membership_witness(block_number, note_commitment);
let witness = get_note_hash_membership_witness(header.global_variables.block_number as u32, note_hash);

// 3) Prove that the commitment is in the note hash tree
assert(
header.state.partial.note_hash_tree.root
== compute_merkle_root(note_commitment, witness.index, witness.path), "Proving note inclusion failed"
assert_eq(
header.state.partial.note_hash_tree.root, compute_merkle_root(note_hash, witness.index, witness.path), "Proving note inclusion failed"
);
// --> Now we have traversed the trees all the way up to archive root.
}

pub fn prove_note_inclusion<Note, N>(
note_with_header: Note,
pub fn prove_note_inclusion<Note, N>(note: Note, context: PrivateContext) where Note: NoteInterface<N> {
_note_inclusion(note, context.historical_header);
}

pub fn prove_note_inclusion_at<Note, N>(
note: Note,
block_number: u32, // The block at which we'll prove that the note exists
context: PrivateContext
) where Note: NoteInterface<N> {
let note_commitment = compute_note_hash_for_consumption(note_with_header);
let header = context.get_header_at(block_number);

prove_note_commitment_inclusion(note_commitment, block_number, context);
_note_inclusion(note, header);
}
17 changes: 12 additions & 5 deletions yarn-project/aztec-nr/aztec/src/history/note_validity.nr
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,24 @@ use crate::{
context::PrivateContext,
history::{
note_inclusion::prove_note_inclusion,
note_inclusion::prove_note_inclusion_at,
nullifier_non_inclusion::prove_note_not_nullified,
nullifier_non_inclusion::prove_note_not_nullified_at,
},
note::note_interface::NoteInterface,
};

pub fn prove_note_validity<Note, N>(note: Note, context: &mut PrivateContext) where Note: NoteInterface<N> {
prove_note_inclusion(note, *context);
prove_note_not_nullified(note, context);
}

// A helper function that proves that a note is valid at the given block number
pub fn prove_note_validity<Note, N>(
note_with_header: Note,
block_number: u32, // The block at which we'll prove that the note exists
pub fn prove_note_validity_at<Note, N>(
note: Note,
block_number: u32,
context: &mut PrivateContext
) where Note: NoteInterface<N> {
prove_note_inclusion(note_with_header, block_number, *context);
prove_note_not_nullified(note_with_header, block_number, context);
prove_note_inclusion_at(note, block_number, *context);
prove_note_not_nullified_at(note, block_number, context);
}
58 changes: 45 additions & 13 deletions yarn-project/aztec-nr/aztec/src/history/nullifier_inclusion.nr
Original file line number Diff line number Diff line change
@@ -1,32 +1,64 @@
use dep::std::merkle::compute_merkle_root;
use dep::protocol_types::header::Header;

use crate::{
context::PrivateContext,
oracle::get_nullifier_membership_witness::get_nullifier_membership_witness,
note::{
utils::compute_siloed_nullifier,
note_interface::NoteInterface,
},
};

pub fn prove_nullifier_inclusion(
nullifier: Field,
block_number: u32, // The block at which we'll prove that the note exists
context: PrivateContext
) {
// 1) Get block header from oracle and ensure that the block hash is included in the archive.
let header = context.get_header_at(block_number);

// 2) Get the membership witness of the nullifier
let witness = get_nullifier_membership_witness(block_number, nullifier);
fn _nullifier_inclusion(nullifier: Field, header: Header) {
// 1) Get the membership witness of the nullifier
let witness = get_nullifier_membership_witness(header.global_variables.block_number as u32, nullifier);

// 3) Check that the witness we obtained matches the nullifier
// 2) Check that the witness we obtained matches the nullifier
assert(witness.leaf_preimage.nullifier == nullifier, "Nullifier does not match value in witness");

// 4) Compute the nullifier tree leaf
// 3) Compute the nullifier tree leaf
let nullifier_leaf = witness.leaf_preimage.hash();

// 5) Prove that the nullifier is in the nullifier tree
// 4) Prove that the nullifier is in the nullifier tree
assert(
header.state.partial.nullifier_tree.root
== compute_merkle_root(nullifier_leaf, witness.index, witness.path), "Proving nullifier inclusion failed"
);
// --> Now we have traversed the trees all the way up to archive root and verified that the nullifier
// was not yet included in the nullifier tree.
}

pub fn prove_nullifier_inclusion(nullifier: Field, context: PrivateContext) {
_nullifier_inclusion(nullifier, context.historical_header);
}

pub fn prove_nullifier_inclusion_at(
nullifier: Field,
block_number: u32, // The block at which we'll prove that the note exists
context: PrivateContext
) {
let header = context.get_header_at(block_number);

_nullifier_inclusion(nullifier, header);
}

pub fn prove_note_is_nullified<Note, N>(
note: Note,
context: &mut PrivateContext
) where Note: NoteInterface<N> {
let nullifier = compute_siloed_nullifier(note, context);

_nullifier_inclusion(nullifier, context.historical_header);
}

pub fn prove_note_is_nullified_at<Note, N>(
note: Note,
block_number: u32,
context: &mut PrivateContext
) where Note: NoteInterface<N> {
let nullifier = compute_siloed_nullifier(note, context);
let header = context.get_header_at(block_number);

_nullifier_inclusion(nullifier, header);
}
41 changes: 27 additions & 14 deletions yarn-project/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use dep::std::merkle::compute_merkle_root;
use dep::protocol_types::header::Header;

use crate::{
context::PrivateContext,
note::{
utils::compute_siloed_nullifier,
note_header::NoteHeader,
note_interface::NoteInterface,
},
oracle::get_nullifier_membership_witness::get_low_nullifier_membership_witness,
Expand All @@ -14,16 +14,9 @@ use crate::{
},
};

pub fn prove_nullifier_non_inclusion(
nullifier: Field,
block_number: u32, // The block at which we'll prove that the nullifier does not exists
context: PrivateContext
) {
// 1) Get block header from oracle and ensure that the block is included in the archive.
let header = context.get_header_at(block_number);

// 2) Get the membership witness of a low nullifier of the nullifier
let witness = get_low_nullifier_membership_witness(block_number, nullifier);
fn _nullifier_non_inclusion(nullifier: Field, header: Header) {
// 1) Get the membership witness of a low nullifier of the nullifier
let witness = get_low_nullifier_membership_witness(header.global_variables.block_number as u32, nullifier);

// 3) Prove that the nullifier is not included in the nullifier tree

Expand All @@ -49,12 +42,32 @@ pub fn prove_nullifier_non_inclusion(
// was not yet included in the nullifier tree.
}

pub fn prove_nullifier_not_included(nullifier: Field, context: PrivateContext) {
_nullifier_non_inclusion(nullifier, context.historical_header);
}

pub fn prove_nullifier_not_included_at(nullifier: Field, block_number: u32, context: PrivateContext) {
let header = context.get_header_at(block_number);

_nullifier_non_inclusion(nullifier, header);
}

pub fn prove_note_not_nullified<Note, N>(
note_with_header: Note,
note: Note,
context: &mut PrivateContext
) where Note: NoteInterface<N> {
let nullifier = compute_siloed_nullifier(note, context);

_nullifier_non_inclusion(nullifier, context.historical_header);
}

pub fn prove_note_not_nullified_at<Note, N>(
note: Note,
block_number: u32, // The block at which we'll prove that the note was not nullified
context: &mut PrivateContext
) where Note: NoteInterface<N> {
let nullifier = compute_siloed_nullifier(note_with_header, context);
let nullifier = compute_siloed_nullifier(note, context);
let header = context.get_header_at(block_number);

prove_nullifier_non_inclusion(nullifier, block_number, *context);
_nullifier_non_inclusion(nullifier, header);
}
39 changes: 34 additions & 5 deletions yarn-project/aztec-nr/aztec/src/history/public_value_inclusion.nr
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use dep::protocol_types::{
constants::GENERATOR_INDEX__PUBLIC_LEAF_INDEX,
header::Header,
hash::pedersen_hash,
address::{
AztecAddress
},
};
use dep::std::merkle::compute_merkle_root;

use crate::{
context::PrivateContext,
oracle::get_public_data_witness::{
get_public_data_witness,
PublicDataWitness,
},
utils::{
full_field_less_than,
Expand All @@ -18,20 +21,46 @@ use crate::{
pub fn prove_public_value_inclusion(
value: Field, // The value that we want to prove is in the public data tree
storage_slot: Field, // The storage slot in which the value is stored
contract_address: AztecAddress, // The contract we want to look into
context: PrivateContext
) {
_public_value_inclusion(
value,
storage_slot,
contract_address,
context.historical_header
);
}

pub fn prove_public_value_inclusion_at(
value: Field, // The value that we want to prove is in the public data tree
storage_slot: Field, // The storage slot in which the value is stored
contract_address: AztecAddress, // The contract we want to look into
block_number: u32, // The block at which we'll prove that the note exists
context: PrivateContext
) {
// 1) Get block header from oracle and ensure that the block hash is included in the archive.
let header = context.get_header_at(block_number);

// 2) Compute the leaf slot by siloing the storage slot with our own address
_public_value_inclusion(value, storage_slot, contract_address, header);
}

fn _public_value_inclusion(
value: Field,
storage_slot: Field,
contract_address: AztecAddress,
header: Header
) {
// 1) Compute the leaf slot by siloing the storage slot with the contract address
let public_value_leaf_slot = pedersen_hash(
[context.this_address().to_field(), storage_slot],
[contract_address.to_field(), storage_slot],
GENERATOR_INDEX__PUBLIC_LEAF_INDEX
);

// 3) Get the membership witness of the slot
let witness = get_public_data_witness(block_number, public_value_leaf_slot);
let witness = get_public_data_witness(
header.global_variables.block_number as u32,
public_value_leaf_slot
);

// 4) Check that the witness matches the corresponding public_value
let preimage = witness.leaf_preimage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,15 @@ impl<T> StablePublicState<T> {
// Read the value from storage (using the public tree)
let fields = storage_read(self.storage_slot);

// TODO: The block_number here can be removed when using the current header in the membership proof.
let block_number = private_context.get_header().global_variables.block_number;

// Loop over the fields and prove their inclusion in the public tree
for i in 0..fields.len() {
// TODO: Update membership proofs to use current header (Requires #4179)
// Currently executing unnecessary computation:
// - a membership proof of the header(block_number) in the history
// - a membership proof of the value in the public tree of the header
prove_public_value_inclusion(
fields[i],
self.storage_slot + i,
block_number as u32,
(*private_context).this_address(),
(*private_context),
)
}
Expand Down
Loading

0 comments on commit 37ecf2c

Please sign in to comment.