Byte-identical outputalpha
What does "byte-identical to moc" mean, what does it buy you, and how is it verified?
Byte-identical means cmp returns zero: the same source, compiled by two different compilers or in two different places, produces wasm files that agree on every byte. Not "semantically equivalent", not "same size", not "passes the same tests".
The constraint is that this is a claim about pairs, and moxzi makes three different pairs of it. They are proven by different gates and they are not interchangeable.
Three claims, three gates#
| Claim | Pair being compared | Gate | Corpus |
|---|---|---|---|
moxzi output == reference moc output | CompileEnhanced vs moc -no-link | scripts/corpus_run.sh, scripts/byteparity_run.py | moc's own test/run |
| Two moxzi compiler builds agree | BASELINE compiler.wasm vs CANDIDATE compiler.wasm | scripts/compiler_byte_neutral.sh | 221 programs from test/run-drun |
| The same compiler agrees across hosts | Chrome tab vs CLI; on-chain vs local | scripts/web_page_compile_gate.sh, scripts/web_mops_gate.sh | the compiler itself, plus mops projects |
The first is a correctness claim measured against an independent implementation. The second is a neutrality claim: it says a refactor changed nothing observable, and it is far cheaper to run than the first because it never interprets Motoko under moc -r — it just runs two builds and diffs. The third is what makes "one compiler, four places" a measurement rather than an assertion.
What it buys you#
Reproducible builds. The artifact does not depend on which of the four front ends produced it. A customer can run an on-chain build, run the same build locally, and cmp the two files. Every artifact carries a provenance line naming the compiler that made it by SHA-256 (moxzi info prints the loaded compiler and linker hashes), so the comparison is anchored to a specific binary rather than to a version string.
Tamper-evident provenance. This is the point of the on-chain builder. A build whose bytes were produced by a canister anyone can audit, from sources anyone can hash, is evidence no local toolchain can offer — but only because the local build reproduces it exactly. Without byte identity the on-chain artifact would be unverifiable, and an unverifiable artifact from a trusted party is just a trusted party.
A refactor gate that cannot be argued with. Most of the compiler's hard work has been performance work: splitting a function so its wasm frame stops costing every recursion level, packing finished function bodies to bytes at definition time, converting a pass from async* to a pull-driven state machine. Each of those changes message counts, memory profiles and instruction budgets, and none of them may change one byte of output. PAR=6 bash scripts/compiler_byte_neutral.sh answers that in one run.
Transitivity. Behavior comparisons chain the same way. The differential harness established that the native runtime matches a real IC replica across moc's corpus; the browser gate then compares the browser runtime against the native one over 149 programs with zero diverging. Browser == native and native == replica gives browser == replica without ever needing a replica in the browser gate, which is what makes that gate fast enough to run over everything.
How the sweeps actually work#
compiler_byte_neutral.sh copies moc's run-drun corpus, rewrites bare actor to persistent actor exactly as the other harnesses do, filters to programs that declare an actor and do not reference ic:/canister: URLs, then builds each one twice — once with MOXZI_COMPILER=$BASELINE, once with $CANDIDATE — and cmps the results. Outcomes are classified, not summed: SAME, DIFFER, BOTHFAIL (the corpus contains programs the toolchain does not accept, which is not a regression), and ONLYNEW/ONLYOLD (built by one compiler and not the other, which is).
Two safeguards in that script are worth knowing about, because both exist as a result of a gate that once passed while asserting nothing:
- A run where
sameis zero fails. If the linker is missing, every programBOTHFAILs and the summary would otherwise report "0 differing" as success. make alpha-checkrefuses to start ifcompiler.wasmorlinker.wasmis absent, because every downstream gate skips-as-pass without them.
web_corpus_gate.sh runs in batches, each its own node process, because past roughly a hundred memory64 modules V8 stops handing out memory and every subsequent program traps identically — a cascade that looks like a systematic failure. Programs the browser cannot host (no management canister; no way to preempt a running call) are named, not counted as agreement.
The known drift#
One difference is open and recorded rather than fixed: the counter byte-parity probe reports exactly one byte differing from the reference, in the name section. It appears in every validation block in PROGRESS.md as "the KNOWN pre-existing 1-byte name-section drift", and the probes assert diffs=1 for that program specifically so it cannot grow silently. The name section carries debug names only; it does not affect execution. It is still a difference, and it is stated here rather than rounded off.
Things you cannot do#
| Not possible | Why |
|---|---|
Compare a linked artifact against a -no-link one | Linking embeds the RTS, prunes exports and rewrites sections. Compare like with like, or link both. |
| Read byte identity as proof of semantic correctness | It proves two compilers agree, over the programs compared. A shared misunderstanding of the language stays invisible. That is what the differential runtime harness and the corpus are for. |
| Expect every corpus program to compile | BOTHFAIL is a normal outcome. The sweeps measure agreement among programs both compilers accept, and report the rejected count separately. |
| Run the sweeps in CI today | Both need the reference corpus checkout and roughly 15 minutes each. They run in a weekly job and always in make alpha-check before a tag (see docs/ci.md). |
| Diff two artifacts built with different flags | --debug, --no-idl and the metadata options change the output legitimately. Byte identity is a claim about identical inputs. |
Next#
- Self-hosting and fixed points — the strongest byte-identity claim in the project, and why it is stronger than a corpus.
- Trust model — what reproducible bytes do and do not buy you per front end.
- Architecture — where
compiler.wasmandlinker.wasmcome from.