Skip to content

feat!: Aztec v6 (@aztec-labs), block-duration-ms input, SHA-pinned actions - #3

Merged
alejoamiras merged 7 commits into
mainfrom
worktree-aztec-v6-update
Oct 1, 2026
Merged

alejoamiras merged 7 commits into
mainfrom
worktree-aztec-v6-update

Conversation

@alejoamiras

@alejoamiras alejoamiras commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Moves aztec-benchmark to Aztec v6 and unblocks aztec-standards#38.

Changes

  • Aztec v6. v6 renamed its packages from @aztec/* to @aztec-labs/*, and the peers now follow at >=6.0.0-0 <7. The package version becomes 6.0.0-rc.1; v5 users stay on 5.0.1.
  • New block-duration-ms input on pr-benchmark.yml and update-baseline.yml. With the local network's default 3 s blocks, a transaction can use at most 55,836 DA gas, and aztec-standards' Vault class publish needs 63,776. Setting "6000" (mainnet's block time) raises the limit to 117,624. Leaving the input empty keeps today's behaviour.
  • Every action pinned to a commit SHA. The workflows used floating tags like setup-aztec@v0, so a caller pinning our workflow didn't actually pin what ran.
  • Small hardening:
    • the reusable workflows no longer persist the checkout token;
    • pre-release.yml no longer uses secrets: inherit;
    • no ${{ }} inside run: blocks;
    • the action calls npx --no. The unscoped aztec-benchmark npm package belongs to someone else, and plain npx could download and run it.

Testing

  • aztec-standards CI: its scratch PR fix: action name defi-wonderland/aztec-benchmark#45 ran against this branch.
    • With "6000", the Vault benchmark passes.
    • With the input omitted, it fails exactly as before, at 55,836.
    • With "6s", it stops in the first step.
    • update-baseline passes.
  • Local v6 network: it reports exactly 55,836 and 117,624. The packed 6.0.0-rc.1 ran a benchmark end to end.
  • Build output: the built JS is byte-identical to 5.0.1, because the Aztec imports are only used as types.

Notes

  • Please squash-merge. Merging also publishes a canary build to npm; that is existing behaviour.
  • Follow-ups for separate PRs: npm trusted publishing (OIDC), a CI check that actions stay pinned, and narrower workflow permissions.
Releasing 6.0.0-rc.1 (after merge)
  1. Set S to the squash commit on main, then tag it: git tag -s v6.0.0-rc.1 $S -m v6.0.0-rc.1 && git push origin v6.0.0-rc.1.
  2. Create the release: gh release create v6.0.0-rc.1 --verify-tag --target main --prerelease --generate-notes. The target must be main, not a SHA, or publish.yml skips publishing.
  3. In the publish.yml run, confirm the head SHA is $S, then approve the Publisher environment. It publishes under the rc dist-tag, and latest stays at 5.0.1.
  4. If the run was skipped, dispatch it from main instead: gh workflow run publish.yml --ref main -f version=6.0.0-rc.1.

🤖 Generated with Claude Code

alejoamiras and others added 7 commits September 30, 2026 14:32
Floating tags (setup-aztec@v0, create-or-update-comment@v4, checkout@v4,
upload-artifact@v4, setup-node@v4) let upstream change what runs, and a
caller's SHA pin on these reusable workflows did not pin them.

Also stop persisting the checkout token in the reusable workflows (PR
code and installers run in the same job) and stop passing all repo
secrets to the upstream pre-release workflow, which uses none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move ${{ }} expressions used inside run: into step env (publish.yml
version/tag checks, the comment-minimize step), quote $GITHUB_OUTPUT, and
make the action's npx call refuse to install: the unscoped
`aztec-benchmark` npm package belongs to a third party.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lows

Callers can set the local network's SEQ_BLOCK_DURATION_MS. The per-tx DA
gas cap scales with blocks per checkpoint: the 3 s default admits 55836,
6000 ms (mainnet's block duration) admits 117624, enough for large
contract-class publications. The value is validated before checkout because
Aztec parses it with parseFloat ("6s" would mean 6 ms); empty keeps today's
environment untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rity model

Replace the non-existent @v0 refs with commit-SHA pins, add contents: read
to the example permissions, complete the PR Benchmark inputs table, and
explain why the per-tx DA cap depends on block duration.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Aztec v6 renamed its npm scope from @Aztec to @aztec-labs. Peers are now
@aztec-labs/aztec.js and @aztec-labs/wallets at >=6.0.0-0 <7 (any 6.0.0
pre-release, since upstream's latest tag points at a nightly), and
config.aztecVersion moves to 6.0.0-rc.1.

The CLI only uses these packages in type positions, so the emitted
dist/*.js is byte-identical to 5.0.1; only the .d.ts specifiers change.

BREAKING CHANGE: requires @aztec-labs/* v6 peers; v5 (@aztec/*) consumers stay on 5.0.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-echo invariant

The trigger warning applies to pr-benchmark.yml only (update-baseline runs
on push), and on fork PRs the failed comment step also skips the baseline
upload. The validator comment now records why the value is never echoed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
alejoamiras added a commit to AztecProtocol/aztec-standards that referenced this pull request Sep 30, 2026
The Vault benchmark's setup publishes the Vault contract class (63,776 DA
gas). The local network's default 3s blocks cap a tx at 55,836, and
aztec-benchmark's reusable workflows had no way to change that.

Pin both workflows to AztecProtocol/aztec-benchmark#3, which adds a
block-duration-ms input, and pass 6000 (mainnet's 6s blocks: 117,624).
This is a pre-release commit; swap it for the v6.0.0-rc.1 tag commit
before merging.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@alejoamiras
alejoamiras merged commit 879fa93 into main Oct 1, 2026
4 checks passed
@alejoamiras
alejoamiras deleted the worktree-aztec-v6-update branch October 1, 2026 18:12
alejoamiras added a commit to AztecProtocol/aztec-standards that referenced this pull request Oct 13, 2026
#38)

* fix(vault): compute share<>asset conversions in a 256-bit intermediate

The conversions compute `a * b / denominator`. Done natively in u128 the
intermediate product overflows for large-but-legitimate inputs; Noir
range-checks u128, so the transaction reverts rather than wrapping. That
is an availability bug (audit F-004): a vault whose totals reach the
range can no longer be deposited to or withdrawn from, permanently
locking every participant's funds. Both sites carried TODOs.

New `conversion.nr` module with a `mul_div` primitive that widens both
operands to noir-bignum's U256 (the same library the escrow's key
derivation already uses), multiplies and divides there, then narrows the
quotient back to u128, asserting it fits. U256 arithmetic is modulo
2^256 and the largest possible product, (2^128-1)^2, is 2^129-1 short of
that modulus, so the product is always exact — no modular wraparound.

Rounding is unchanged: both old and new return
floor(p/d) + (round_up && p%d != 0). For every input the old code
accepted the results are identical; the widening only extends the domain
that succeeds. This matters because the vault's economic safety depends
on rounding always favouring the vault — a shift in either direction
would leak value between the vault and its depositors.

`mul_div` also rejects a zero denominator explicitly: noir-bignum's
constrained udiv_mod fails on it, but its unconstrained path assumes
non-zero and would return a meaningless witness. Unreachable from the
vault (denominators are total_assets+1 and total_supply+vault_offset
with vault_offset >= 1) but the helper is now safe in isolation.

Extracting mul_div into its own module is what makes the overflow
boundary testable at all: a real vault cannot be driven to a 2^128
supply in a test, but the primitive can be called directly at its edges.

Also adds `ensureVaultContractClassPublished` to the JS test utils.
Publishing just the class is what the vault tests actually need and is
substantially cheaper in DA gas than deploying a throwaway Vault to get
the class published as a side effect. It is idempotent — publication
emits a nullifier keyed on the class id, so a second publish of the same
class is rejected with "Existing nullifier"; the helper checks
registration state first, the same way DeployMethod does.

Validated: vault_contract 195 Noir tests (188 pre-existing all still
green — the strongest evidence rounding did not shift — plus 7 new
covering limb round-trips, rounding direction both ways, products that
previously overflowed, max operands, and the two revert guards).
aztec compile OK. Codex adversarial review: correct, rounding invariance
proven algebraically, no value-leak path; its zero-denominator hardening
is applied.

Note: the vault README still describes the overflow as a known issue.
That warning block is rewritten in PR #24 (unmerged); leaving it there
avoids a three-way conflict.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci: run JS tests against mainnet block geometry

`aztec start --local-network` defaults to 3s blocks. With 72s slots that
packs 21 blocks into a checkpoint, and the per-tx DA admission limit is
`ceil(daBudget / blocks * 1.5)` = 55,882 DA gas. Mainnet runs 6s blocks
(10 blocks per checkpoint) and admits 117,668.

The protocol picks that 1.5 multiplier deliberately, and says so in
aztec stdlib `gas/tx_gas_limits.ts`: it is set "so the largest tx we want
to support — a maximal contract class registration (~97k DA gas) — fits
a single block under v5 mainnet geometry (72s slots, 6s blocks -> 10
blocks per checkpoint)". The default local geometry therefore advertises
a limit well below the ~97k the protocol guarantees for exactly this
kind of transaction, and rejects contracts that are valid on the network
we ship to.

Publishing the Vault contract class costs ~64k DA gas. That is fine on
mainnet and inside the protocol's stated envelope, but over the local
55,882 cap. Note this is not specific to any one change: main's Vault
already sits at ~54k, i.e. 97% of the local ceiling, so essentially any
growth in that contract trips it.

Reusable workflows do not inherit the caller's `env`, and
aztec-ci-actions' run-tests.yml exposes no knob for this, so the JS job
is inlined here (`run-js-tests: false` on the reusable call) purely to
own the environment. It still calls the same pinned `setup-aztec` and
`js-tests` composite actions, so behaviour is otherwise unchanged.

NOTE FOR REVIEWERS: this renames the check from "checks / JS Tests" to
"JS Tests". Any branch protection rule naming the old check needs
updating, or it will block merges waiting on a check that no longer runs.

The better long-term fix is upstream — either the local network should
default to mainnet geometry, or run-tests.yml should expose the knob.
Worth raising with the Aztec CI folks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci: run benchmarks at mainnet block geometry

The Vault benchmark's setup publishes the Vault contract class (63,776 DA
gas). The local network's default 3s blocks cap a tx at 55,836, and
aztec-benchmark's reusable workflows had no way to change that.

Pin both workflows to AztecProtocol/aztec-benchmark#3, which adds a
block-duration-ms input, and pass 6000 (mainnet's 6s blocks: 117,624).
This is a pre-release commit; swap it for the v6.0.0-rc.1 tag commit
before merging.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci: pin aztec-benchmark to the v6.0.0-rc.1 release

879fa93 is the squash commit of aztec-benchmark#3 that v6.0.0-rc.1 tags.
Its pr-benchmark.yml and update-baseline.yml are byte-identical to the
d623993 head they were verified at; only publish.yml differs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore(deps): bump @aztec-foundation/aztec-benchmark to 6.0.0-rc.1

5.0.1 declared @aztec/aztec.js and @aztec/wallets peers (<6) and typed
its Benchmark base class against them, so against this repo's
@aztec-labs/* v6 packages the peers were unmet and the benchmark files
carried 33 type errors (unseen: tsx does not type-check). 6.0.0-rc.1 peers
@aztec-labs/* >=6.0.0-0 <7 and the benchmark files type-check clean.

Its gitHead and SLSA provenance name 879fa93, the commit both benchmark
workflows are pinned to.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(bump-aztec-version): aztec-benchmark v6 peers, pins and the DA cap

The benchmark gotcha described 5.0.1's v5 peers as current. 6.0.0-rc.1
is the first @aztec-labs release. A peer mismatch fails nothing (yarn
warns, tsconfig skips benchmarks/, tsx doesn't type-check), so document
the explicit typecheck. Record that the devDependency and both workflow
pins move together, and the local-network DA cap that the Vault class
publication hits without 6s blocks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(vault): the conversion intermediate is 256-bit, not 512

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci: stop passing `secrets: inherit` to reusable workflows (#47)

None of the called workflows (aztec-ci-actions run-tests.yml, aztec-benchmark
pr-benchmark.yml and update-baseline.yml, at both the v5.0.1 and v6.0.0-rc.1
pins) declare `on.workflow_call.secrets` or read `secrets.*`, and the repo has
no repo, org or environment secrets. `inherit` passes nothing today, but it
would hand any secret added later to workflows that live in other repos, so a
future pin bump that starts reading one gets it without us ever opting in.

A called workflow always gets `github.token` / `secrets.GITHUB_TOKEN`, scoped by
the caller job's `permissions`, so the benchmark PR comment keeps working.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* ci: typecheck src and the benchmarks (#48)

Vitest and tsx (which runs the benchmarks) only strip types, so a type error
in either never failed CI. Add `yarn typecheck` (`tsc --noEmit`) and run it in
both js-tests jobs, after the setup step's compile + codegen write src/artifacts.

tsconfig changes so the project type-checks clean:
- `target/**/*` matched no JSON: an include glob only picks up .json files
  when the pattern itself ends in `.json`. Every generated src/artifacts/*.ts
  imports its `target/*.json`, which `composite` then rejects with TS6307.
  Now `target/**/*.json`.
- include `benchmarks`, which nothing type-checked before.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(vault): restore an accurate capacity warning and test the fix on the contract path

The conversions still add `vault_offset` to the share supply and 1 to total
assets in u128 before `mul_div`. A deposit can leave the supply above
2^128 - 1 - vault_offset, after which every conversion reverts, withdrawals
included; with a large offset that takes few assets. The READMEs had dropped
the overflow warning entirely: restore it as a precise second known issue, and
correct comments that called the remaining overflow impossible.

`conversion.nr`'s tests run constrained; the vault runs it in public. Add a
2^100-scale deposit and redeem through the contract (fails on the old u128 math)
and a case that only the `hi < 256` narrowing bound rejects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(skills): point the bump skill at `yarn typecheck`

It still described a temporary tsconfig and said tsconfig.json skips
benchmarks/, both stale since typecheck joined CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants