Skip to content
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
Expand Up @@ -20,7 +20,7 @@ You can create proofs for these elements at any past block height:
- **Note inclusion** - prove a note existed in the note hash tree
- **Note validity** - prove a note existed and wasn't nullified at a specific block
- **Nullifier inclusion/non-inclusion** - prove a nullifier was or wasn't in the nullifier tree
- **Contract deployment** - prove a contract was deployed or initialized
- **Contract deployment** - prove a contract's bytecode was published or initialized

Common use cases:
- Verify ownership of an asset from another contract without revealing which specific note
Expand All @@ -29,7 +29,7 @@ Common use cases:

## Prove note inclusion

Import the trait:
Import the function:

#include_code history_import noir-projects/noir-contracts/contracts/app/claim_contract/src/main.nr rust

Expand All @@ -42,10 +42,10 @@ Prove a note exists in the note hash tree:
To prove a note was valid (existed AND wasn't nullified) at a historical block:

```rust
use dep::aztec::history::note_validity::ProveNoteValidity;
use dep::aztec::history::note::assert_note_was_valid_by;

let header = self.context.get_anchor_block_header();
header.prove_note_validity(hinted_note, &mut self.context);
assert_note_was_valid_by(header, hinted_note, &mut self.context);
```

This verifies both:
Expand All @@ -57,8 +57,10 @@ This verifies both:
To prove against state at a specific past block (not just the anchor block):

```rust
use dep::aztec::history::note::assert_note_existed_by;

let historical_header = self.context.get_block_header_at(block_number);
historical_header.prove_note_inclusion(hinted_note);
assert_note_existed_by(historical_header, hinted_note);
```

:::warning
Expand All @@ -70,45 +72,45 @@ Using `get_block_header_at` adds ~3k constraints to prove Archive tree membershi
To prove a note has been spent/nullified:

```rust
use dep::aztec::history::nullifier_inclusion::ProveNoteIsNullified;
use dep::aztec::history::note::assert_note_was_nullified_by;

let header = self.context.get_anchor_block_header();
header.prove_note_is_nullified(hinted_note, &mut self.context);
assert_note_was_nullified_by(header, confirmed_note, &mut self.context);
```

## Prove contract deployment
## Prove contract bytecode was published

To prove a contract was deployed at a historical block:
To prove a contract's bytecode was published at a historical block:

```rust
use dep::aztec::history::contract_inclusion::ProveContractDeployment;
use dep::aztec::history::deployment::assert_contract_bytecode_was_published_by;

let header = self.context.get_anchor_block_header();
header.prove_contract_deployment(contract_address);
assert_contract_bytecode_was_published_by(header, contract_address);
```

You can also prove a contract was initialized (constructor was called):

```rust
use dep::aztec::history::contract_inclusion::ProveContractInitialization;
use dep::aztec::history::deployment::assert_contract_was_initialized_by;

let header = self.context.get_anchor_block_header();
header.prove_contract_initialization(contract_address);
assert_contract_was_initialized_by(header, contract_address);
```

## Available proof traits

The `aztec::history` module provides these traits:

| Trait | Purpose |
|-------|---------|
| `ProveNoteInclusion` | Prove note exists in note hash tree |
| `ProveNoteValidity` | Prove note exists and is not nullified |
| `ProveNoteIsNullified` | Prove note's nullifier is in nullifier tree |
| `ProveNoteNotNullified` | Prove note's nullifier is not in nullifier tree |
| `ProveNullifierInclusion` | Prove a raw nullifier exists |
| `ProveNullifierNonInclusion` | Prove a raw nullifier does not exist |
| `ProveContractDeployment` | Prove a contract was deployed |
| `ProveContractNonDeployment` | Prove a contract was not deployed |
| `ProveContractInitialization` | Prove a contract was initialized |
| `ProveContractNonInitialization` | Prove a contract was not initialized |
## Available proof functions

The `aztec::history` module provides these functions:

| Function | Module | Purpose |
|----------|--------|---------|
| `assert_note_existed_by` | `history::note` | Prove note exists in note hash tree |
| `assert_note_was_valid_by` | `history::note` | Prove note exists and is not nullified |
| `assert_note_was_nullified_by` | `history::note` | Prove note's nullifier is in nullifier tree |
| `assert_note_was_not_nullified_by` | `history::note` | Prove note's nullifier is not in nullifier tree |
| `assert_nullifier_existed_by` | `history::nullifier` | Prove a raw nullifier exists |
| `assert_nullifier_did_not_exist_by` | `history::nullifier` | Prove a raw nullifier does not exist |
| `assert_contract_bytecode_was_published_by` | `history::deployment` | Prove a contract's bytecode was published |
| `assert_contract_bytecode_was_not_published_by` | `history::deployment` | Prove a contract's bytecode was not published |
| `assert_contract_was_initialized_by` | `history::deployment` | Prove a contract was initialized |
| `assert_contract_was_not_initialized_by` | `history::deployment` | Prove a contract was not initialized |
31 changes: 30 additions & 1 deletion docs/docs-developers/docs/resources/migration_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,35 @@ Aztec is in active development. Each version may introduce breaking changes that

## TBD

### [aztec-nr] History module refactored to use standalone functions

The `aztec::history` module has been refactored to use standalone functions instead of traits. This changes the calling convention from method syntax to function syntax.

```diff
- use dep::aztec::history::note_inclusion::ProveNoteInclusion;
+ use dep::aztec::history::note::assert_note_existed_by;

let block_header = context.get_anchor_block_header();
- let confirmed_note = block_header.prove_note_inclusion(hinted_note);
+ let confirmed_note = assert_note_existed_by(block_header, hinted_note);
```

**Function name and module mapping:**

| Old (trait method) | New (standalone function) |
|--------------------|---------------------------|
| `history::note_inclusion::prove_note_inclusion` | `history::note::assert_note_existed_by` |
| `history::note_validity::prove_note_validity` | `history::note::assert_note_was_valid_by` |
| `history::nullifier_inclusion::prove_nullifier_inclusion` | `history::nullifier::assert_nullifier_existed_by` |
| `history::nullifier_inclusion::prove_note_is_nullified` | `history::note::assert_note_was_nullified_by` |
| `history::nullifier_non_inclusion::prove_nullifier_non_inclusion` | `history::nullifier::assert_nullifier_did_not_exist_by` |
| `history::nullifier_non_inclusion::prove_note_not_nullified` | `history::note::assert_note_was_not_nullified_by` |
| `history::contract_inclusion::prove_contract_deployment` | `history::deployment::assert_contract_bytecode_was_published_by` |
| `history::contract_inclusion::prove_contract_non_deployment` | `history::deployment::assert_contract_bytecode_was_not_published_by` |
| `history::contract_inclusion::prove_contract_initialization` | `history::deployment::assert_contract_was_initialized_by` |
| `history::contract_inclusion::prove_contract_non_initialization` | `history::deployment::assert_contract_was_not_initialized_by` |
| `history::public_storage::public_storage_historical_read` | `history::storage::public_storage_historical_read` |

### [Aztec.js] Transaction sending API redesign

The old chained `.send().wait()` pattern has been replaced with a single `.send(options)` call that handles both sending and waiting.
Expand Down Expand Up @@ -4308,7 +4337,7 @@ await expect(

### [Aztec.nr] Public storage historical read API improvement

`history::public_value_inclusion::prove_public_value_inclusion` has been renamed to `history::public_storage::public_storage_historical_read`, and its API changed slightly. Instead of receiving a `value` parameter it now returns the historical value stored at that slot.
`history::public_value_inclusion::prove_public_value_inclusion` has been renamed to `history::storage::public_storage_historical_read`, and its API changed slightly. Instead of receiving a `value` parameter it now returns the historical value stored at that slot.

If you were using an oracle to get the value to pass to `prove_public_value_inclusion`, drop the oracle and use the return value from `public_storage_historical_read` instead:

Expand Down
12 changes: 6 additions & 6 deletions noir-projects/aztec-nr/aztec/src/context/private_context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -746,9 +746,9 @@ impl PrivateContext {
///
/// ## Historical Notes
///
/// If you need to assert that a note existed _at some specific time in the past_, instead of simply proving that it
/// exists in the current anchor block, use
/// [crate::history::note_inclusion::ProveNoteInclusion::prove_note_inclusion] instead.
/// If you need to assert that a note existed _by some specific block in the past_, instead of simply proving that it
/// exists by the current anchor block, use
/// [crate::history::note::assert_note_existed_by] instead.
///
/// ## Cost
///
Expand Down Expand Up @@ -784,9 +784,9 @@ impl PrivateContext {
///
/// ## Historical Nullifiers
///
/// If you need to assert that a nullifier existed _at some specific time in the past_, instead of simply proving
/// that it exists in the current anchor block, use
/// [crate::history::nullifier_inclusion::ProveNullifierInclusion::prove_nullifier_inclusion] instead.
/// If you need to assert that a nullifier existed _by some specific block in the past_, instead of simply proving
/// that it exists by the current anchor block, use
/// [crate::history::nullifier::assert_nullifier_existed_by] instead.
///
/// ## Public vs Private
///
Expand Down
71 changes: 0 additions & 71 deletions noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr

This file was deleted.

56 changes: 56 additions & 0 deletions noir-projects/aztec-nr/aztec/src/history/deployment.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//! Contract deployments.

use dep::protocol_types::{
abis::block_header::BlockHeader, address::AztecAddress,
constants::CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS, hash::compute_siloed_nullifier,
traits::ToField,
};

use crate::history::nullifier::{assert_nullifier_did_not_exist_by, assert_nullifier_existed_by};

// This is tested in `noir-projects/noir-contracts/test_contract/src/test.nr because we cannot define a contract
// from within aztec.nr (due to the contract macro).

pub fn assert_contract_bytecode_was_published_by(
block_header: BlockHeader,
contract_address: AztecAddress,
) {
let bytecode_publishing_nullifier = compute_siloed_nullifier(
CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
contract_address.to_field(),
);

assert_nullifier_existed_by(block_header, bytecode_publishing_nullifier);
}

pub fn assert_contract_bytecode_was_not_published_by(
block_header: BlockHeader,
contract_address: AztecAddress,
) {
let bytecode_publishing_nullifier = compute_siloed_nullifier(
CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
contract_address.to_field(),
);

assert_nullifier_did_not_exist_by(block_header, bytecode_publishing_nullifier);
}

pub fn assert_contract_was_initialized_by(
block_header: BlockHeader,
contract_address: AztecAddress,
) {
let initialization_nullifier =
compute_siloed_nullifier(contract_address, contract_address.to_field());

assert_nullifier_existed_by(block_header, initialization_nullifier);
}

pub fn assert_contract_was_not_initialized_by(
block_header: BlockHeader,
contract_address: AztecAddress,
) {
let initialization_nullifier =
compute_siloed_nullifier(contract_address, contract_address.to_field());

assert_nullifier_did_not_exist_by(block_header, initialization_nullifier);
}
21 changes: 15 additions & 6 deletions noir-projects/aztec-nr/aztec/src/history/mod.nr
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
//! Proofs of Aztec history.
//!
//! ## Data Availability
//!
//! Functions in these modules assert statements about the past state of the Aztec network. While this is possible in
//! theory, actual network nodes might not have the information required to produce proofs at relatively old blocks.
//!
//! In particular, many nodes prune old state and do not keep records of the different state trees (note hashes,
//! nullifiers, public storage, etc.) at blocks older than a couple hours, which are required in order to produce the
//! sibling paths these functions need.
//!
//! An archive node is therefore required when using any of these functions on non-recent blocks.

pub mod contract_inclusion;
pub mod note_inclusion;
pub mod note_validity;
pub mod nullifier_inclusion;
pub mod nullifier_non_inclusion;
pub mod public_storage;
pub mod deployment;
pub mod note;
pub mod nullifier;
pub mod storage;
mod test;
Loading
Loading