https://x.com/afat/status/2098104815653912657
0.1.0-alpha.5 (2026-09-09)
Three themes: 256-bit integers for EVM and cryptographic work, thousands of actors on
one machine for simulation and swarm workloads, and verifiable provenance — a canister
you can prove was built from stated sources by a compiler running on the Internet Computer.
Added: native Nat256 and Nat128
256-bit arithmetic is unavoidable in EVM and cryptographic code. Motoko’s Nat is an
arbitrary-precision bignum, so every operation on a 256-bit value allocated on the heap.
Nat256 and Nat128 are now first-class fixed-width types held as 32- and 16-byte values,
with no allocation for chained arithmetic.
Complete from the start: + - * / % ** and their wrapping forms (+% -% *% **%), & | ^,
<< >>, all six comparisons, debug_show, conversions to and from Nat, Nat64, each
other and big-endian Blob, candid nat on the wire, and stable variables that survive an
upgrade.
These are an extension: moc cannot compile a program that uses them. Programs that don’t
are unaffected and still compile to identical bytes.
Added: running thousands of actors on one machine
Each Motoko actor is a separate WebAssembly instance owning its own memory, so a few thousand
of them exhausted a laptop. Four changes together make dense actor workloads practical —
simulations, swarms, one-actor-per-entity designs:
--ephemeralmarks a module as disposable, and the runtime skips the per-message
durability snapshot it would otherwise take. 129× the message throughput, for actors
whose state need not survive a crash. It is recorded in the artifact rather than set by the
host, so a module built durable cannot be run ephemerally by accident.--compact-rtslinks a runtime with smaller garbage-collector partitions, for
off-chain targets. A leaf actor’s committed memory drops from 4.06 MB to 0.31 MB.
--actor-stack-kiband a memory cap tune it further.- Shared module code. Identical modules are compiled once and instantiated many times,
in the server and in the browser. - Hibernation (
moxzid --live-cap N). Beyond N live instances the least recently used
actor is written to disk and its instance dropped; the next message to it wakes it in
35–45 ms. 10,000 actors run on a laptop with memory bounded by the cap — uncapped
they need roughly 26 GB. Snapshots are compressed (5.42 MB → 0.04 MB each, since an actor’s
heap is mostly zeros) and identical module code is stored once rather than per actor.
Demo: a marble swarm with one actor per marble, thousands of them, rendered in a browser tab
or streamed from the server over a WebSocket.
Added: publishing a canister with verifiable provenance
You can now build a canister on the Internet Computer itself and publish it to an
ICRC-118 registry with a record of how it was
built — so anyone can check that the deployed bytes came from the sources claimed.
moxzi publishwrites a registry entry carrying the source digest, the build options,
the compiler version and the artifact hashes.- The compiler links the module itself, so the hash it vouches for is the hash of the
bytes you actually deploy. The entry records which canister did the linking. moxzi verifychecks a deployed canister against that record.- The registry pulls the compiler’s word. After the upload,
moxzi publishasks the
registry to call the compiler canister with the LINKED hash (attestLinked); the registry
files the answer as the compiler’s own ICRC-126 attestation and the CLI prints the verdict:
verified(built on-chain),unverified(the compiler never linked these bytes – a
local build publishes fine and says so), orDIVERGENT(an open report outranks every
attestation). Change one byte of a verified wasm and the answer is a definite no. moxzi publishrefuses a--compact-rtsartifact unless--allow-offchain: it is the
off-chain runtime’s build, and a registry is what on-chain orchestrators install from.--previous <version>records what a release upgrades from, giving the registry a real
upgrade path.moxzi deprecatemarks a version superseded without removing it.--repoand--commitrecord where the source came from, read from git automatically.
A modified working tree is not auto-filled: a commit hash that doesn’t describe the bytes
being published would be worse than none.moxzi build --gzipwrites a gzipped module beside the wasm. Needed when a canister is
passed as a call argument, which is capped near 2 MiB regardless of how the receiving
canister was installed — a typical Motoko canister compresses several-fold.icrc126-mo, a new Motoko package implementing
ICRC-126 wasm verification: attestations,
divergence reports, and a verification policy where a single attestation from a compiler
canister carries the weight of several independent rebuilds.
Fixed
Miscompilations
debugblocks ran in release builds.debug { … }is meant to be removed entirely by
--release, and never was — so release builds carried debug logging and paid for it. Now
removed, matchingmoc.let (?a, ?b) = e else fbound garbage. Destructuring a tuple with anything other
than plain variables — an option, a literal, a variant tag, a nested record — silently
failed to bind, and using the result trapped with no diagnostic. Worse, a pattern that
should have failed matched instead:let (8, b) = (7, 9)returned9where it must
trap. Affected any tuple destructure whose right-hand side wasn’t a constant.let x : Nat256 = <literal>read out of bounds. A wide literal bound withlet
was stored in the wrong representation and read back as garbage rather than as zero.- Timers armed before an actor hibernated never fired. The deadline was preserved but
nothing scheduled it, so the task simply never ran until unrelated traffic woke the actor. returninside a localasyncfunction poisoned the function’s result type toAny.- Linked modules lost their function names, making profiles and traps harder to read.
Programs that were accepted but should have been rejected
Each of these compiled here and is refused by moc, so code could pass here and fail on a
real deployment:
- Colliding field or variant-tag hashes (M0122, M0019), duplicate definitions
(M0018) and duplicate bindings in a pattern (M0017). - Stable variables of non-stable type (M0131) — the check was missing entirely.
sharedsilently dropped from generic function types, so a shared function’s body could
disagree with its declared control flow (M0078, M0079, M0041).systemcapability errors both over- and under-reported (M0077).- Non-productive type definitions (M0157), contextual-dot calls with the wrong arity
(M0233), generic calls with mismatched arguments (M0098), signed literals against
non-fixed-width types (M0050), and M0257. ?,weakand??accepted type forms the grammar does not allow there, such as
?actor {}and?async T.
Also added: M0155 warns that Nat subtraction may trap, and M0195.
Diagnostics
- An unannotated
<system>function, and an actor class body, now hold the system
capability as they should. - Member types are checked before bodies, so the reported error is the first real one.
- A non-toplevel
actor(M0069) is reported after type checking, so a program with two
errors reports the same onemocreports. --packagepointing at a missing directory is an error (M0012) rather than silently
ignored.
Contributions back to Motoko:
- Nat256/128 attempt to port back to oCaml and moc: https://github.com/rivvirtech/motoko/tree/wide-ints-1.16 (@ggreif had talked about doing something like this before and he is far more qualified, but here is an attempt)
- Updates to the RTS for allowing a smaller default heap and GC threshold: https://github.com/rivvirtech/motoko/tree/compact-partitions
Coming in Alpha 6
- Get back to parity with moc (now at 1.16.0)
- Loop optimization when dealing with array indexes.
- More motoko magic. I want 100,000 marbles
- What else?