Skip to content

feat: update to Noir 1.0.0-beta.25 - #311

Open
TomAFrench wants to merge 10 commits into
reilabs:mainfrom
noir-lang:tf/update-to-beta.25
Open

feat: update to Noir 1.0.0-beta.25#311
TomAFrench wants to merge 10 commits into
reilabs:mainfrom
noir-lang:tf/update-to-beta.25

Conversation

@TomAFrench

Copy link
Copy Markdown

Overview

Updates Lampe's targeted Noir version from 1.0.0-beta.19 (with the stdlib still extracted at beta.14) to 1.0.0-beta.25: the extractor is ported to the new noirc APIs, the vendored stdlib is re-vendored and re-extracted at beta.25, and the handwritten stdlib theorem layer plus the testing projects are repaired so everything builds green. A new doc describes the version-update process end to end.

Extractor (src/)

Ports to the beta.25 noirc APIs: DependencyId::DataType, comptime-integer Type::Constant, flipped Type::Array(E, N) argument order, BigInt/byte literals, the reworked deprecation attributes, and the new QuotedType::Location / HirStatement::TraitAssociatedConstant (the latter's placeholder globals are skipped). Two behavioural changes were needed:

  • Builtin/foreign trait impl methods no longer have elaborated bodies upstream, so the extractor now synthesizes a body forwarding to the intrinsic.
  • Trait default methods materialize per impl with Self bound to itself; Self is now resolved to the impl's concrete type while generating an impl, and identity type-variable bindings no longer recurse forever.

Lampe library (Lampe/)

  • Bool bit decompositions: Noir's bit decompositions now return bool arrays instead of u1 arrays. toLeBits/toBeBits/modulusLeBits/modulusBeBits move to .bool with Bool.toDigit/Digit.toBool conversions and roundtrip simp lemmas in Lampe.Data.Digits; the Hoare intro rules are restated accordingly.
  • The new poseidon2_config_state_size foreign builtin is modeled as the constant 4, matching the width-4 (BN254) Poseidon2 configuration Lampe formalizes.
  • Builtin.mkFormatString is now implemented (it was an unprovable stub; beta.25's poseidon2_permutation builds a format string for its static assert).
  • The eDSL gains a dedicated token for the unitEq builtin (beta.25's stdlib exercises Eq for unit, and maximal munch tokenizes #_unitEq as the #_unit literal followed by Eq).
  • Struct gains cross-member indexTpl/replaceTuple' simp lemmas, needed now that BoundedVec methods read and write through references.

Stdlib spec (stdlib/)

stdlib/src is re-vendored from the pinned rev (collections/map.nr and collections/vec.nr are gone, integer.nr, internal/ and meta/location.nr are new, slices have become vectors), the extracted std-1.0.0-beta.14 package is replaced by std-1.0.0-beta.25, and the theorem layer is repaired:

  • &self migration: BoundedVec::get/get_unchecked/len, the BoundedVec and array higher-order methods (map/mapi/for_each/for_eachi/fold/reduce/all/any/concat/sort_via/sort), Option::is_some/is_none, and check_shuffle (now over &[T; N] operands) are all restated in the by-reference style and re-proved.
  • u1 removal / bool bits: the u1 Eq/arith/bit specs are deleted; to_le_bits/to_be_bits, pow_32 and sgn0 proofs are converted to the bool-array decomposition (with Mathlib's lex List.LE' locally erased, since Bool is a LinearOrder and it would shadow the core list order the proofs use). bytes32_to_field was removed upstream, so its spec goes too.
  • BoundedVec semantics: pop no longer zeroes the popped slot, from_parts lost its zeroing loop, from_parts_unchecked is deprecated (excluded from the extracted env, spec deleted), and extend_from_bounded_vec bounds its loop with cmp::min (covered by a new min_u32_spec). Eq is re-proved against the new element-wise active-prefix comparison.
  • Poseidon2: the sponge struct is gone upstream; the new chunked finish_ref absorption is modeled directly (addToState/chunkState/finishDigest) and finish/finish_ref/write/RATE/CAPACITY/POSEIDON2_CONFIG_STATE_SIZE are re-proved.
  • Embedded curves: EmbeddedCurvePoint lost is_infinite; infinity is canonically (0, 0). The Lampe curve model is reshaped and the point/scalar/MSM specs re-proved — the round-trip lemmas now require [Bn254.Prime p] so that (0, 0) is off-curve.
  • Pedersen: the removed hash::from_field_unsafe is bridged via EmbeddedCurveScalar::from_field's safe decomposition.
  • Misc: tuple Ord impls now end in a value-if, so the tuple3/4/5 proofs are restructured; Collections/Map specs are gone with the upstream module; some files explicitly raise heartbeat/recursion limits, as the larger extracted env pushes them over the defaults.

Testing projects (testing/)

Re-extracted at beta.25 with proofs repaired. The Merkle projects' vendored deps/hasher-0.0.0 snapshots are replaced by direct path requires on ../../hasher/lampe (the extractor no longer vendors dependencies that ship their own lampe directory, so the snapshots could never be regenerated), and Merkle gains a clean.sh matching Base64's. The Rust extraction tests now run on a 16MiB thread, as the beta.25 elaborator overflows the default 2MiB test-thread stack in debug builds.

Docs

docs/ gains a guide to the Noir version update process: every place the targeted version is referenced, the update procedure, and the testing steps that validate an update.

Describes every place the targeted Noir version is referenced, the
update procedure, and the testing steps that validate an update.
Bumps the pinned noir-lang/noir rev (previously the beta.19 release
commit) to the v1.0.0-beta.25 tag and ports the extractor to the new
noirc APIs:

- DependencyId::Struct is now DependencyId::DataType.
- Type::Constant carries a comptime Integer instead of a
  (FieldElement, Kind) pair, and Type::Array's element/size order
  flipped to Array(E, N).
- HirLiteral::Integer holds a BigInt and HirLiteral::Str holds bytes.
- Attributes::get_deprecated_note was replaced by get_deprecated, and
  SecondaryAttributeKind::Deprecated gained a deny flag.
- QuotedType::Location and HirStatement::TraitAssociatedConstant are
  new; the latter also surfaces as placeholder globals which are now
  skipped.
- activate_lsp_mode and report_all grew parameters; u1 is gone.
- Builtin/foreign trait impl methods no longer have elaborated bodies,
  so a body forwarding to the intrinsic is synthesized instead.
- Trait default methods materialize per impl with Self bound to
  itself; Self is now resolved to the impl's concrete type (and
  excluded from generic patterns) while generating an impl, and
  identity type-variable bindings no longer recurse forever.

The in-crate Noir test fixtures are updated for language changes
(as_slice -> as_vector, signed type-level constants need suffixed
literals).
Replaces stdlib/src with noir_stdlib/src from the pinned rev and bumps
the package version that names the extracted std package. Notable
upstream changes: collections/map.nr and collections/vec.nr are gone,
integer.nr, internal/ and meta/location.nr are new, and slices have
become vectors.
- The versioned stdlib struct names baked into the embedded curve
  builtins move to std-1.0.0-beta.25.
- The new stdlib poseidon2_config_state_size foreign builtin is
  modeled as the constant 4, matching the width-4 (BN254) Poseidon2
  configuration Lampe formalizes.
- The eDSL gains a dedicated token for the unitEq builtin: beta.25's
  stdlib exercises Eq for the unit type, and the generic builtin call
  syntax cannot parse it because maximal munch tokenizes #_unitEq as
  the #_unit literal followed by Eq.
Noir's bit decompositions now produce bool arrays instead of u1 arrays:

- toLeBits/toBeBits/modulusLeBits/modulusBeBits move to .bool, with
  Bool.toDigit / Digit.toBool conversions (and roundtrip simp lemmas)
  in Lampe.Data.Digits.
- The corresponding Hoare intro rules are restated accordingly.
- Struct gains cross-member indexTpl/replaceTuple' simp lemmas, needed
  now that BoundedVec methods read and write through references.
Replaces the extracted std-1.0.0-beta.14 package with std-1.0.0-beta.25
and updates the handwritten theorem layer for the upstream changes:

- u1 is gone: its Eq/arith/bit specs are deleted.
- Bit decompositions return bool arrays: the to_le/be_bits, pow_32 and
  sgn0 proofs are converted (with Mathlib's lex List.LE' locally erased,
  since Bool is a LinearOrder and it would shadow the core list order
  the proofs use). bytes32_to_field was removed upstream, so its spec
  goes too.
- Tuple Ord impls end in a value-if; the tuple3/4/5 proofs are
  restructured.
- BoundedVec::get/get_unchecked/len take &self now: their specs are
  restated in the reference style. pop no longer zeroes the popped
  slot, from_parts lost its zeroing loop, from_parts_unchecked is
  deprecated (and excluded from the extracted env, so its spec is
  deleted), and extend_from_bounded_vec bounds its loop with cmp::min
  (covered by a new min_u32_spec).
- The larger extracted env pushes some proofs over the default
  heartbeat/recursion limits; those files raise them explicitly.
- Collections/Map is gone upstream.

Known remaining work (previously masked by upstream build failures):
Stdlib/Array/CheckShuffle.lean, Stdlib/Hash/Poseidon2.lean and
Stdlib/Option.lean still fail against the beta.25 extraction (the same
by-reference migration); tracked in PROOF_REPAIRS.md.
Completes the stdlib proof repairs so `stdlib/lampe` builds green:

- BoundedVec map/mapi/for_each/for_eachi and array higher-order methods
  (map/mapi/for_each/for_eachi/fold/reduce/all/any/concat/sort_via/sort)
  restated ref-style for the by-reference &self migration
- BoundedVec Eq re-proved against the new element-wise active-prefix
  comparison; check_shuffle restated over &[T; N] operands
- Poseidon2: the sponge struct is gone upstream; model the new chunked
  finish_ref absorption directly (addToState/chunkState/finishDigest) and
  re-prove finish/finish_ref/write/RATE/CAPACITY/POSEIDON2_CONFIG_STATE_SIZE
- Option: is_some/is_none restated ref-style; expect re-proved
- EmbeddedCurvePoint lost is_infinite: infinity is canonically (0, 0);
  reshape the Lampe curve model and re-prove the point/scalar/MSM specs
  (round-trip lemmas now require [Bn254.Prime p] so (0,0) is off-curve)
- Pedersen: bridge the removed hash::from_field_unsafe via
  EmbeddedCurveScalar::from_field's safe decomposition
- Lampe: implement Builtin.mkFormatString (was an unprovable stub; beta.25's
  poseidon2_permutation builds a format string for its static assert)
The Merkle projects' vendored deps/hasher-0.0.0 snapshots are replaced by
direct path requires on ../../hasher/lampe: the extractor no longer vendors
dependencies that ship their own lampe directory, so the stale snapshots
could never be regenerated. Merkle also gains a clean.sh (matching Base64's)
so generated extraction output is refreshed on every test run.

MerkleFromScratch's sgn0 spec is restated for beta.25's bool bit
decomposition, and Sort's handwritten env-inclusion proof plus the checked-in
lakefiles/manifests now reference std-1.0.0-beta.25.
The beta.25 elaborator recurses deeply enough to overflow the default
2MiB test-thread stack in debug builds, so the test helpers now run
extraction on a 16MiB thread. Also adds a #[must_use] clippy had started
asking for.
@TomAFrench
TomAFrench marked this pull request as ready for review July 29, 2026 10:35
@TomAFrench TomAFrench changed the title Update to Noir 1.0.0-beta.25 feat: update to Noir 1.0.0-beta.25 Jul 29, 2026
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.

1 participant