Skip to content
Draft
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 @@ -33,8 +33,8 @@ This returns up to `MAX_NOTE_HASH_READ_REQUESTS_PER_CALL` notes without filterin
### Step 2: Retrieve notes from storage

```rust
// Returns BoundedVec<HintedNote<MyNote>, ...>
let hinted_notes = storage.my_notes.at(owner).get_notes(options);
// Returns BoundedVec<ConfirmedNote<MyNote>, ...>
let confirmed_notes = storage.my_notes.at(owner).get_notes(options);
```

:::tip get_notes vs pop_notes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ pub contract MyContract {
};
use uint_note::UintNote;

// The storage struct can have any name, but is typically called `Storage`. It must have the `#[storage]` macro applied to it.
// The storage struct must be named `Storage` and must have the `#[storage]` macro applied to it.
// This struct must also have a generic type called C or Context.
#[storage]
struct Storage<Context> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,15 @@ Public events are emitted as plaintext logs, similar to Solidity events.

## Emit unstructured public logs

For unstructured data, use `emit_public_log` directly on the context:
For unstructured data, use `emit_public_log_unsafe` directly on the context. It takes a tag (placed at the first field of the emitted log, which nodes use to index logs) followed by the data:

```rust
self.context.emit_public_log("My message");
self.context.emit_public_log([1, 2, 3]);
self.context.emit_public_log_unsafe(0, "My message");
self.context.emit_public_log_unsafe(0, [1, 2, 3]);
```

The tag should be domain-separated to prevent collisions with unrelated log types. Prefer `self.emit(event)` where possible, which handles tagging automatically.

## Query public logs

Query public logs from offchain applications using the Aztec node:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ Note: The `Owned` wrapper requires calling `.at(owner)` to access the underlying

#### `get_notes`

Retrieves notes the account has access to. You can optionally provide filtering options. Returns `RetrievedNote` instances:
Retrieves notes the account has access to. You can optionally provide filtering options. Returns `ConfirmedNote` instances:

```rust title="private_set_get_notes" showLineNumbers
let options = NoteGetterOptions::with_filter(filter_notes_min_sum, amount);
Expand All @@ -591,7 +591,7 @@ let notes = owner_balance.get_notes(options);

#### `pop_notes`

This function pops (gets, removes and returns) the notes the account has access to. Unlike `get_notes`, this immediately nullifies the notes and returns them directly (not wrapped in `RetrievedNote`):
This function pops (gets, removes and returns) the notes the account has access to. Unlike `get_notes`, this immediately nullifies the notes and returns them directly (not wrapped in `ConfirmedNote`):

```rust title="private_set_pop_notes" showLineNumbers
let options = NoteGetterOptions::new().set_limit(1);
Expand All @@ -602,13 +602,13 @@ let note = owner_balance.pop_notes(options).get(0);

#### `remove`

Will remove a note from the `PrivateSet` if it previously has been read from storage. Takes a `RetrievedNote` as returned by `get_notes`:
Will remove a note from the `PrivateSet` if it previously has been read from storage. Takes a `ConfirmedNote` as returned by `get_notes`:

```rust
let options = NoteGetterOptions::new();
let retrieved_notes = self.storage.balances.at(owner).get_notes(options);
let confirmed_notes = self.storage.balances.at(owner).get_notes(options);
// ... select a note to remove ...
self.storage.balances.at(owner).remove(retrieved_notes.get(0));
self.storage.balances.at(owner).remove(confirmed_notes.get(0));
```

Note that if you obtained the note via `get_notes`, it's much better to use `pop_notes`, as `pop_notes` results in significantly fewer constraints due to avoiding an extra hash and read request check.
Expand Down
1,391 changes: 1,222 additions & 169 deletions docs/developer_versioned_docs/version-v4.3.1/docs/cli/aztec_cli_reference.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ wallet [options] [command]
**Options:**

- `-V --version` - output the version number
- `-d --data-dir <string>` - Storage directory for wallet data (default: "/home/josh/.aztec/wallet")
- `-d --data-dir <string>` - Storage directory for wallet data (default: "~/.aztec/wallet")
- `-p --prover <string>` - The type of prover the wallet uses (choices: "wasm", "native", "none", default: "native", env: PXE_PROVER)
- `-n --node-url <string>` - URL of the Aztec node to connect to (default: "http://host.docker.internal:8080", env: AZTEC_NODE_URL)
- `-n --node-url <string>` - URL of the Aztec node to connect to (default: "http://localhost:8080", env: AZTEC_NODE_URL)
- `-h --help` - display help for command

### Subcommands
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,24 +102,25 @@ Your contract can verify the deployment or initialization state of other contrac
- Conditional logic based on initialization

```rust
use aztec::history::contract_inclusion::{
ProveContractDeployment,
ProveContractNonDeployment,
ProveContractInitialization,
ProveContractNonInitialization,
use aztec::history::deployment::{
assert_contract_bytecode_was_not_published_by,
assert_contract_bytecode_was_published_by,
assert_contract_was_initialized_by,
assert_contract_was_not_initialized_by,
};

// Prove a contract is deployed
header.prove_contract_deployment(contract_address);
// Prove a contract's bytecode was published by a given block
assert_contract_bytecode_was_published_by(block_header, contract_address);

// Prove a contract is NOT deployed
header.prove_contract_non_deployment(contract_address);
// Prove a contract's bytecode was NOT published by a given block
assert_contract_bytecode_was_not_published_by(block_header, contract_address);

// Prove a contract is initialized
header.prove_contract_initialization(contract_address);
// Prove a contract was initialized by a given block
// (init_hash is the contract's initialization hash, obtainable via get_contract_instance)
assert_contract_was_initialized_by(block_header, contract_address, init_hash);

// Prove a contract is NOT initialized
header.prove_contract_non_initialization(contract_address);
// Prove a contract was NOT initialized by a given block
assert_contract_was_not_initialized_by(block_header, contract_address, init_hash);
```

These functions prove inclusion or non-inclusion of the corresponding nullifiers in the nullifier tree at a given block.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ pub contract Counter {

This defines a contract called `Counter`.

:::note Clear the scaffold's placeholder test
The scaffolded `counter_test/src/lib.nr` imports the default contract name (`Main`) we just replaced above, so it now fails to compile. Tests aren't used in this tutorial - replace its contents with a single-line stub so `aztec compile` stays clean:

```rust
// Tests are out of scope for this tutorial. See https://docs.aztec.network/aztec-nr/testing_contracts for examples.
```

:::

## Imports

We need to define some imports.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ cd hardhat-aztec-example
yarn add @aztec/aztec.js@4.3.1 @aztec/accounts@4.3.1 @aztec/stdlib@4.3.1 @aztec/wallets@4.3.1 tsx
```

:::note Match the `@aztec/l1-contracts` version
The starter repo pins its `@aztec/l1-contracts` dependency to an older release. In `package.json`, update the tag to match the network version used in this tutorial, then run `yarn install` again:

```json
"@aztec/l1-contracts": "git+https://github.com/AztecProtocol/l1-contracts.git#v4.3.1"
```

The L1 interfaces the portal imports later in this tutorial must match the contracts deployed by your running network.
:::

Now start the local network in another terminal:

```bash
Expand Down Expand Up @@ -274,7 +284,7 @@ aztec compile

We have built the L2 NFT contract. This is the L2 representation of an NFT that is locked on the L1 bridge.

The L2 bridge is the contract that talks to the L1 bridge through cross-chain messaging. You can read more about this protocol [here](../../../docs/foundational-topics/ethereum-aztec-messaging/index.md).
The L2 bridge is the contract that talks to the L1 bridge through cross-chain messaging. You can read more about this protocol [here](../../foundational-topics/ethereum-aztec-messaging/index.md).

```mermaid
graph LR
Expand Down Expand Up @@ -667,6 +677,19 @@ const inboxAddress = nodeInfo.l1ContractAddresses.inboxAddress.toString();
> <sup><sub><a href="https://github.com/AztecProtocol/aztec-packages/blob/v4.3.1/docs/examples/ts/token_bridge/index.ts#L1-L42" target="_blank" rel="noopener noreferrer">Source code: docs/examples/ts/token_bridge/index.ts#L1-L42</a></sub></sup>


:::warning Adjust the artifact imports for this project's layout
The snippet above comes from the monorepo's runnable example, and its artifact imports point at that repo's layout. In the Hardhat project used in this tutorial, replace the four artifact imports with:

```typescript
import NFTPortal from "../artifacts/contracts/NFTPortal.sol/NFTPortal.json" with { type: "json" };
import SimpleNFT from "../artifacts/contracts/SimpleNFT.sol/SimpleNFT.json" with { type: "json" };
import { NFTBridgeContract } from "../contracts/aztec/artifacts/NFTBridge.js";
import { NFTPunkContract } from "../contracts/aztec/artifacts/NFTPunk.js";
```

`npx hardhat compile` writes the Solidity artifacts to `artifacts/contracts/`, and the `aztec codegen` commands from earlier wrote the TypeScript bindings to `contracts/aztec/artifacts/`. Hardhat artifacts also store the bytecode as a plain string, so in the deployment snippet below use `SimpleNFT.bytecode` and `NFTPortal.bytecode` instead of `.bytecode.object`.
:::

You now have wallets for both chains, correctly connected to their respective chains. Next, deploy the L1 contracts:

```typescript title="deploy_l1_contracts" showLineNumbers
Expand Down Expand Up @@ -1021,8 +1044,8 @@ console.log("NFT withdrawn to L1\n");

You can now try the whole flow with:

```typescript
npx hardhat run scripts/index.ts --network localhost
```bash
npx tsx scripts/index.ts
```

## What You Built
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ This returns up to `MAX_NOTE_HASH_READ_REQUESTS_PER_CALL` notes without filterin
### Step 2: Retrieve notes from storage

```rust
// Returns BoundedVec<HintedNote<MyNote>, ...>
let hinted_notes = storage.my_notes.at(owner).get_notes(options);
// Returns BoundedVec<ConfirmedNote<MyNote>, ...>
let confirmed_notes = storage.my_notes.at(owner).get_notes(options);
```

:::tip get_notes vs pop_notes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ pub contract MyContract {
};
use uint_note::UintNote;

// The storage struct can have any name, but is typically called `Storage`. It must have the `#[storage]` macro applied to it.
// The storage struct must be named `Storage` and must have the `#[storage]` macro applied to it.
// This struct must also have a generic type called C or Context.
#[storage]
struct Storage<Context> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,15 @@ Public events are emitted as plaintext logs, similar to Solidity events.

## Emit unstructured public logs

For unstructured data, use `emit_public_log` directly on the context:
For unstructured data, use `emit_public_log_unsafe` directly on the context. It takes a tag (placed at the first field of the emitted log, which nodes use to index logs) followed by the data:

```rust
self.context.emit_public_log("My message");
self.context.emit_public_log([1, 2, 3]);
self.context.emit_public_log_unsafe(0, "My message");
self.context.emit_public_log_unsafe(0, [1, 2, 3]);
```

The tag should be domain-separated to prevent collisions with unrelated log types. Prefer `self.emit(event)` where possible, which handles tagging automatically.

## Query public logs

Query public logs from offchain applications using the Aztec node. Raw public logs are
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -434,25 +434,25 @@ Note: The `Owned` wrapper requires calling `.at(owner)` to access the underlying

#### `get_notes`

Retrieves notes the account has access to. You can optionally provide filtering options. Returns `RetrievedNote` instances:
Retrieves notes the account has access to. You can optionally provide filtering options. Returns `ConfirmedNote` instances:

#include_code private_set_get_notes /noir-projects/noir-contracts/contracts/test/pending_note_hashes_contract/src/main.nr rust

#### `pop_notes`

This function pops (gets, removes and returns) the notes the account has access to. Unlike `get_notes`, this immediately nullifies the notes and returns them directly (not wrapped in `RetrievedNote`):
This function pops (gets, removes and returns) the notes the account has access to. Unlike `get_notes`, this immediately nullifies the notes and returns them directly (not wrapped in `ConfirmedNote`):

#include_code private_set_pop_notes /noir-projects/noir-contracts/contracts/test/pending_note_hashes_contract/src/main.nr rust

#### `remove`

Will remove a note from the `PrivateSet` if it previously has been read from storage. Takes a `RetrievedNote` as returned by `get_notes`:
Will remove a note from the `PrivateSet` if it previously has been read from storage. Takes a `ConfirmedNote` as returned by `get_notes`:

```rust
let options = NoteGetterOptions::new();
let retrieved_notes = self.storage.balances.at(owner).get_notes(options);
let confirmed_notes = self.storage.balances.at(owner).get_notes(options);
// ... select a note to remove ...
self.storage.balances.at(owner).remove(retrieved_notes.get(0));
self.storage.balances.at(owner).remove(confirmed_notes.get(0));
```

Note that if you obtained the note via `get_notes`, it's much better to use `pop_notes`, as `pop_notes` results in significantly fewer constraints due to avoiding an extra hash and read request check.
Expand Down
41 changes: 41 additions & 0 deletions docs/docs-developers/docs/cli/aztec_cli_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,47 @@ aztec setup-protocol-contracts [options]

### aztec start

Starts Aztec infrastructure components. Module flags can be combined to run several components in a single process (e.g. `--node --sequencer`).

**Usage:**

```bash
aztec start [options]
```

**Examples:**

```bash
# Start a complete local development network
aztec start --local-network

# Start a full node
aztec start --node

# Start a sequencer node
aztec start --node --sequencer
```

**Common options:**

- `--network <value>` - Network to run Aztec on (env: NETWORK)
- `--port <value>` - Port to run the Aztec Services on (default: 8080, env: AZTEC_PORT)
- `--admin-port <value>` - Port to run admin APIs of Aztec Services on (default: 8880, env: AZTEC_ADMIN_PORT)

**Module flags:**

- `--local-network` - Starts the Aztec Local Network: a local Ethereum dev node (Anvil) with the full Aztec protocol deployed on top
- `--node` - Starts an Aztec Node
- `--sequencer` - Starts an Aztec Sequencer
- `--prover-node` - Starts an Aztec Prover Node
- `--prover-broker` - Starts an Aztec proving job broker
- `--prover-agent` - Starts an Aztec Prover Agent
- `--p2p-bootstrap` - Starts an Aztec P2P bootstrap node
- `--bot` - Starts an Aztec transaction bot
- `--txe` - Starts an Aztec TXE (test execution environment)

Each module accepts further namespaced options (e.g. `--sequencer.coinbase`, `--local-network.testAccounts`). For the full per-module option list, see the [node operator CLI reference](/operate/operators/reference/cli-reference).

### aztec test

*No help information available for this command.*
Expand Down
4 changes: 2 additions & 2 deletions docs/docs-developers/docs/cli/aztec_wallet_cli_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ wallet [options] [command]
**Options:**

- `-V --version` - output the version number
- `-d --data-dir <string>` - Storage directory for wallet data (default: "/home/josh/.aztec/wallet")
- `-d --data-dir <string>` - Storage directory for wallet data (default: "~/.aztec/wallet")
- `-p --prover <string>` - The type of prover the wallet uses (choices: "wasm", "native", "none", default: "native", env: PXE_PROVER)
- `-n --node-url <string>` - URL of the Aztec node to connect to (default: "http://host.docker.internal:8080", env: AZTEC_NODE_URL)
- `-n --node-url <string>` - URL of the Aztec node to connect to (default: "http://localhost:8080", env: AZTEC_NODE_URL)
- `-h --help` - display help for command

### Subcommands
Expand Down
27 changes: 14 additions & 13 deletions docs/docs-developers/docs/foundational-topics/contract_creation.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,24 +103,25 @@ Your contract can verify the deployment or initialization state of other contrac
- Conditional logic based on initialization

```rust
use aztec::history::contract_inclusion::{
ProveContractDeployment,
ProveContractNonDeployment,
ProveContractInitialization,
ProveContractNonInitialization,
use aztec::history::deployment::{
assert_contract_bytecode_was_not_published_by,
assert_contract_bytecode_was_published_by,
assert_contract_was_initialized_by,
assert_contract_was_not_initialized_by,
};

// Prove a contract is deployed
header.prove_contract_deployment(contract_address);
// Prove a contract's bytecode was published by a given block
assert_contract_bytecode_was_published_by(block_header, contract_address);

// Prove a contract is NOT deployed
header.prove_contract_non_deployment(contract_address);
// Prove a contract's bytecode was NOT published by a given block
assert_contract_bytecode_was_not_published_by(block_header, contract_address);

// Prove a contract is initialized
header.prove_contract_initialization(contract_address);
// Prove a contract was initialized by a given block
// (init_hash is the contract's initialization hash, obtainable via get_contract_instance)
assert_contract_was_initialized_by(block_header, contract_address, init_hash);

// Prove a contract is NOT initialized
header.prove_contract_non_initialization(contract_address);
// Prove a contract was NOT initialized by a given block
assert_contract_was_not_initialized_by(block_header, contract_address, init_hash);
```

These functions prove inclusion or non-inclusion of the corresponding nullifiers in the nullifier tree at a given block.
Expand Down
Loading
Loading