Skip to content

cert: certify non-empty List literals - #1447

Merged
jasisz merged 6 commits into
mainfrom
cert/list-literals
Sep 26, 2026
Merged

jasisz merged 6 commits into
mainfrom
cert/list-literals

Conversation

@jasisz

@jasisz jasisz commented Sep 26, 2026

Copy link
Copy Markdown
Owner

Second List step for the certificate, stacked on #1445: non-empty List literals.

The first commit is #1446 (the acceptance proofs read the type section only through its cut). Without it, btc-listener's check runs past the 9000-second limit after #1444, so the measurements below need it. It drops out of this diff once #1446 is on main and this branch is rebased.

What changes

  • Wall (Grammar, GrammarLower, GrammarSound, TypeTable, SchemaCore, AcceptedArtifactCore, AcceptanceSoundness): the node list t items now admits a non-empty literal. Its typing needs the cons helper the type table declares for the element type (TypeTable.listCons, the new MCtx.listCons), with the planned signature (t, List<t>) -> List<t>, and every item typed at t. Its lowering is the items, ref.null of the cons struct, and one call of the helper per item. This is exactly emit_mir_list_literal, and the last item is consed first. Its meaning is the cons cells of the items in order (consAll).
  • The helper is proved, not assumed. The producer offers the cons helper as a planned internal function. The new acceptance conjunct consPinned requires every declared helper to be a planned function whose body is the wall's cons plan, one List.prepend of its two parameters (isConsPlan). The agreement proof takes the helper's Contract plus the model fact that its meaning is List.prepend (hConsF), and folds the calls over the reversed items (consCalls_run). fn_certified_group discharges that model fact from the plan (groupModel_consPlan), and fn_certified_total threads it through. The root theorems keep the axioms propext, Classical.choice, Quot.sound. There is no schema change, and the wall id rotates.
  • Producer: the printer prints the items and declares the helper per element type. produce.rs offers the helper with the literal's function, counts it as a call target, and keeps a listCons entry only when its helper is offered. plan_check.rs has the Rust twins of the typing and lowering. Plans.lean writes listCons only when it is non-empty, so a module without literals renders as before, and the snapshots move only by the wall id. Bridge steps gained the simp lemmas that unfold a literal, so a function that returns a literal is now bridged.
  • Byte-binding lint: the pin checks only the helper's body. Checking its slot count and locals as well made the lint count those FnPlan fields as bound for every plan, and lint_flags_the_removed_code_entry_pin caught it.
  • Tests: a printer unit test. In cert_hardening_spec, the clean literal certificate checks, and each of these is refused: the List<Int> helper declared as a user function of the same signature whose plan returns the tail, the helper's own plan changed to return the tail, and the List<Int> and List<String> helpers exchanged. The payment_ops count pin moves from 101 to 106. A strict aver-cert verify of a seven-export literal probe returns CERTIFIED, with 6 of 6 bridges credited.
  • Ratchet: 5 exports and 4 bridges gained in payment_ops, nothing lost (--allow-drop not used).
  • Docs: format §6.1, §6.3 and §7.3, certification.md, CHANGELOG.

Measurements

aver-cert check of btc-listener (commit 5698c8e), one Lean process, AVER_CERT_PHASE_TIMEOUT_SECS=9000:

#1445 merged with main, plus #1446 this branch
checked exports 765 823
law-claims credited 109 / 119 109 / 119
bridged-laws credited (laws on bytes) 16 / 17 16 / 17
source-bridges credited 494 / 494 535 / 535
check wall time 1331 s 1611 s

The census predicted +58 for btc, and all 58 arrive. Examples, projects and certificate fixtures (producer admission): 706 → 733.

Laws on bytes do not move yet. The laws over List functions need bridges for List arguments, which is the decoder PR that comes next.

Tests run

cargo test -p aver-cert --all-features, the printer unit tests, the certificate snapshots, cert_one_build_spec, cert_hardening_spec (42), cert_certify_spec (39, with the payment_ops pin moved), and the cert_verify_spec tripwires (43). Also cargo fmt --check and clippy on both crates.

jasisz and others added 5 commits September 25, 2026 22:36
The plan grammar gains the two List patterns, `[]` and `[head, ..tail]`,
and the two-arm List match the emitter lowers: both arms in either order,
or either one first and `_` second. The wall ports `emit_mir_list_match`
(stash the subject, `ref.is_null`, the `[]` arm in `then`, the head and
tail read from the cons struct into the arm's binders in `else`) and
proves the case in `agreement_step`, so a function that matches on a List,
recursive ones included, is certified for the bytes already emitted. No
helper, no new runtime contract, no schema change; the wall id rotates.

The producer prints the patterns and carries the Rust twins of the arm
pick, the typing and the lowering. Four hardening tests: the clean List
certificate checks, and exchanged arm results, exchanged cons structs and
exchanged head and tail slots decline. The ratchet records 54 gains and no
loss; btc-listener goes from 632 to 765 certified exports.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A type table long enough to be written in pieces (`types_records_0`,
`types_records_1`, ...) left those pieces folded in the `simp` that proves
a bridge's arguments well typed, so the step stopped on an unreduced
record lookup and the bridge fell to `sorry`. btc-listener's records
crossed that length once List matches were certified: 65 of its 494
bridges and one bridged law lost their credit. The typing step now unfolds
every piece of the table but the string segments, which typing never
reads, and btc-listener is back at 494 of 494 bridges and 16 of 17 bridged
laws with 765 certified exports.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…oofs

The package's roles_ok and plans_ok unfolded carrierState,
carrierConfirmed and typeSectionMatches with simp. Each is a match on
the decoded type section, and simp reduced that match before the cut
could rewrite the decode, evaluating the whole type-section decode in the
elaborator. After the Vector version structs changed the type section,
btc-listener's Artifact.lean ran past the 9000-second phase limit.

Unfold these definitions by their unconditional equations with matcher
reduction off, so the decode is replaced by the cut and read only in the
kernel: roles_ok 13 s and plans_ok 68 s on that package, where each ran
for over 10 minutes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A non-empty literal pushes its items, then the empty list, and calls the
per-type cons helper once per item. The plan grammar now admits that
node: its typing needs the cons helper the type table declares for the
element type, with the planned signature (T, List<T>) -> List<T>; its
lowering is the items, ref.null and one call per item; its meaning is the
cons cells of the items in order.

The cons helper is offered as a planned internal function, and a new
acceptance conjunct (consPinned) requires its plan to be the wall's own
cons plan: one List.prepend of its two parameters. So the literal's
calls reach a function whose meaning is proved, not assumed, and the
agreement proof folds the calls over the reversed items. No schema
change; the wall id rotates.

The producer prints the items, declares the helper per element type,
offers the helper with the literal's function, and carries the Rust
twins of the typing and lowering. Bridges of functions that return a
literal unfold it with the new simp lemmas.

Hostile tests: the helper declared as a user function of the same
signature, the helper's plan changed to return the tail, and the helpers
of two instantiations exchanged, each refused. Ratchet: gains only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@jasisz
jasisz changed the base branch from cert/containers to main September 26, 2026 08:45
# Conflicts:
#	CHANGELOG.md
#	aver-cert/assets/wall/current/GrammarLower.lean
#	aver-cert/src/engine/plan.rs
#	aver-cert/src/format.rs
#	docs/certificate-format.md
#	docs/certification.md
#	src/codegen/cert/plan_from_mir.rs
#	tests/cert_certify_spec.rs
#	tests/cert_hardening_spec.rs
#	tests/snapshots/cert_certify_spec__add_one_certificate_package.snap
#	tests/snapshots/cert_certify_spec__wasip2_component_certificate_package.snap
#	tools/cert-baseline.json
@jasisz
jasisz merged commit edc6b70 into main Sep 26, 2026
30 checks passed
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