Skip to content
Open
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
41 changes: 29 additions & 12 deletions noir-projects/protocol-fuzzer/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
A state-machine fuzzer for Aztec contract interactions. It talks to a running
sandbox via a persistent Node.js HTTP bridge (`bridge.mjs`), compares the
sandbox via a persistent Node.js HTTP bridge (`wallet-bridge.mjs`), compares the
sandbox's behavior to an in-memory model, and asserts on any divergence.

Two machines are available:
Expand All @@ -19,16 +19,22 @@ it uses the standard `Token` contract that ships with the wallet CLI:
cargo run -- token --max-steps 100
```

The **side-effect** machine requires the **nightly** sandbox because it deploys custom
contracts compiled against the nightly's aztec-nr. Use `setup-nightly-sandbox.sh` to
automate the full setup (defaults to the last tested nightly tag; pass `--latest` to
try the newest one). See `SANDBOX_INSTRUCTIONS.md` for manual steps.
The **side-effect** machine requires custom contracts. There are two ways to set it up:

**Local setup** (no Docker, uses your repo build):
```
bash setup-local.sh # compiles contracts, starts anvil + node + bridge
cargo run -- side-effect --artifacts-dir contracts/target --max-steps 100
```
bash setup-nightly-sandbox.sh

**Nightly Docker setup** (defaults to the last tested nightly tag; pass `--latest` for newest):
```
bash setup-nightly-sandbox.sh
cargo run -- side-effect --max-steps 100
```
The nightly script places artifacts at `/tmp/` inside the container (the default `--artifacts-dir`).

See `SANDBOX_INSTRUCTIONS.md` for manual nightly steps and troubleshooting.

To replay a specific failure seed:

Expand All @@ -44,8 +50,15 @@ cargo run -- side-effect --max-steps 100000 --seed 0x5a7211231dcd6500
--seed 0xHEX Replay a specific seed
--max-steps N Max fuzzing steps (default: 400)
--max-batch-size N Max parallel sends per batch (default: 8)
--artifacts-dir DIR Contract artifact directory (side-effect only, default: /tmp)
```

> **Note:** `--artifacts-dir` is resolved on the host and sent as-is to the bridge.
> For **local** setup the bridge runs on the host, so use the real path (e.g.
> `contracts/target`). For **nightly Docker** the bridge runs inside the container,
> so the path must be valid inside it — the default `/tmp` works because the nightly
> script places artifacts at `/tmp/*.json` inside the container.

### Parallel batching

Consecutive non-conflicting state-changing commands are batched and fired concurrently,
Expand All @@ -64,12 +77,16 @@ Conflict rules (conservative -- false positives only reduce batch size):
To verify that the sandbox is running correctly, run the integration smoke tests:

```
cargo test -- --ignored --nocapture
ARTIFACTS_DIR=contracts/target cargo test -- --ignored --nocapture
```

These are `#[ignore]`d by default because they require a running sandbox. With
bridge + fast slots, a full suite run takes ~1-2 minutes (~5-13s per transaction).

Environment variables for tests:
- `ARTIFACTS_DIR` -- contract artifact directory (default: `/tmp`)
- `BRIDGE_URL` -- bridge server URL (default: `http://localhost:8089`)

## Contracts

Contract sources live in `contracts/` within this crate, not in `noir-contracts/`. They
Expand All @@ -82,9 +99,9 @@ with oracle calls (like `utilityLog`) that the nightly PXE doesn't support.
- **Parent** (`contracts/parent_contract/`) -- forwards calls to SideEffect for
cross-contract call testing

Artifacts are built by `setup-nightly-sandbox.sh` inside the nightly container and
placed in `contracts/target/` (not checked into git).
Artifacts are built by `setup-local.sh` or `setup-nightly-sandbox.sh` and placed in
`contracts/target/`. Pre-built artifacts are checked into git for convenience.

The setup script auto-detects the nightly commit by matching the container's nargo
hash against `origin/next`. See `SANDBOX_INSTRUCTIONS.md` for the full build pipeline,
version matrix, and troubleshooting.
The nightly setup script auto-detects the nightly commit by matching the container's
nargo hash against `origin/next`. See `SANDBOX_INSTRUCTIONS.md` for the full build
pipeline, version matrix, and troubleshooting.
18 changes: 11 additions & 7 deletions noir-projects/protocol-fuzzer/SANDBOX_INSTRUCTIONS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Protocol Fuzzer: Running with Nightly Docker Sandbox

> **For local development** (no Docker), use `setup-local.sh` instead. It starts
> anvil, the Aztec node, compiles contracts, and launches the bridge — all on the
> host. See `README.md` for quick-start instructions.

## Overview

The protocol fuzzer has two state machines:
Expand All @@ -9,7 +13,7 @@ The protocol fuzzer has two state machines:
- **side-effect**: Fuzzes note lifecycle, nullifier emission, and cross-contract calls via
custom `SideEffect` and `Parent` contracts. **Requires the nightly sandbox.**

Both machines talk to the sandbox via a persistent Node.js HTTP bridge (`bridge.mjs`)
Both machines talk to the sandbox via a persistent Node.js HTTP bridge (`wallet-bridge.mjs`)
that keeps a single CLIWallet instance alive across requests.

## Why the nightly sandbox?
Expand Down Expand Up @@ -69,7 +73,7 @@ for the next block. Four things bring per-transaction time from ~35s down to ~4-

1. **Fast slots.** The setup script starts the sandbox with 5-second L1/L2 slot durations
(default 36s/12s) and disables sequencer timetable enforcement.
2. **Persistent bridge.** `bridge.mjs` keeps a single Node.js wallet instance alive inside
2. **Persistent bridge.** `wallet-bridge.mjs` keeps a single Node.js wallet instance alive inside
the container. Without it, each operation would shell out to the CLI wallet, paying a
~1.5s Node.js cold-start every time.
3. **Parallel batching.** The fuzzer buffers consecutive non-conflicting sends and fires
Expand Down Expand Up @@ -218,14 +222,14 @@ done

### 5. Start the bridge server

The bridge server (`bridge.mjs`) runs inside the container and provides a persistent
The bridge server (`wallet-bridge.mjs`) runs inside the container and provides a persistent
HTTP API that the fuzzer calls:

```bash
docker cp bridge.mjs aztec-sandbox-nightly:/usr/src/yarn-project/bridge.mjs
docker cp wallet-bridge.mjs aztec-sandbox-nightly:/usr/src/yarn-project/wallet-bridge.mjs

docker exec -d aztec-sandbox-nightly \
bash -c 'cd /usr/src/yarn-project && exec node --no-warnings bridge.mjs > /tmp/bridge.log 2>&1'
bash -c 'cd /usr/src/yarn-project && exec node --no-warnings wallet-bridge.mjs > /tmp/bridge.log 2>&1'

# Wait for it to start
curl -s http://localhost:8089/health # {"ok":true}
Expand Down Expand Up @@ -319,7 +323,7 @@ on every operation.

### How the bridge works

`bridge.mjs` runs inside the container and lazily initializes a `CLIWallet` instance
`wallet-bridge.mjs` runs inside the container and lazily initializes a `CLIWallet` instance
on the first request. The Rust fuzzer resolves aliases (`accounts:test0`,
`contracts:test0`) to hex addresses before sending them to the bridge via HTTP POST.

Expand Down Expand Up @@ -347,7 +351,7 @@ on the first request. The Rust fuzzer resolves aliases (`accounts:test0`,
| wallet CLI | `node --no-warnings /usr/src/yarn-project/cli-wallet/dest/bin/index.js` |
| sandbox CLI | `node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js` |
| anvil | `/opt/foundry/bin/anvil` |
| bridge server | `/usr/src/yarn-project/bridge.mjs` |
| bridge server | `/usr/src/yarn-project/wallet-bridge.mjs` |
| bridge log | `/tmp/bridge.log` |

## Stopping
Expand Down
Loading
Loading