Files
ZIPs/docs/audit/implementation-runtimes.md
zeekayandHanzo Dev 27f92fa759 Zoo's Go is nine thousand lines of import lists
An audit read the code and found the proposal that specifies it. Not one ZIP
earns a shipped verdict in any runtime, and the reason is uniform: every
primitive the corpus specifies — ML-DSA, ML-KEM, SLH-DSA, Corona, Pulsar, FHE,
the DEX VM — is reached by a blank import of luxfi/precompile, and no
repository carries a replace directive. The specification is Zoo's; the code
is Lux's.

    | | shipped | partial | none | not assessed |
    | Go   | 0 | 10 | 4 | 132 |
    | C++  | 0 |  0 | 0 | 146 |
    | Rust | 0 |  1 | 0 | 145 |

Two findings behind those numbers. The most substantial original systems code
in the estate is a two-thousand-line Rust Kubernetes operator with four
working custom resources, and no ZIP specifies it. And chains/zoo-evm
registers pulsar where node/vm/factory.go does not, so the binary an operator
actually runs lacks the primitive ZIP-0811's finality is built on.

ZIP-0803 is Final with nothing found in Go and is left unwritten rather than
demoted.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-05 19:18:41 -07:00

6.7 KiB
Raw Permalink Blame History

Implementation audit — Go, C++ and Rust against the ZIP corpus

Where each proposal's implementation-go, implementation-cpp and implementation-rust would come from. One row per assessed ZIP in .audit-runtimes.tsv:

<language>:<zip-number>	<shipped|partial|none>	<evidence>

The evidence is a path and line, or a symbol, that a reader can check. A verdict without its reasoning is a claim nobody can re-derive.

The audit read the code and looked for the ZIP that specifies it, rather than reading 146 proposals and guessing. A ZIP absent from the file was not assessed in that language — which is why not assessed is a column in the index and not a zero.

What was assessed

shipped partial none assessed
Go 0 10 5 15
C++ 0 0 0 0
Rust 0 1 0 1

Sixteen rows over 146 proposals. That is the honest size of the intersection between the ZIP corpus and these three runtimes, and the reason is stated below rather than worked around.

What was left unassessed, and why

Everything Solidity. ZIPs 0016–0037, 0100–0113, 0201–0210, 0300–0306, 0600–0606 and 0700–0703 are token standards, vaults, DAO mechanics and NFT protocols. Their runtime is the EVM. Grading them none in Rust would report that somebody looked for Rust and found none, when the true statement is that Rust was never the language for them.

Everything Python or TypeScript. The 04xx AI series (less the precompile-adjacent 0419 and 0423), the 05xx conservation and ESG series, and 0434 land in gym (an axolotl fork), brain, zoo-ai and models. Same reasoning.

Seven of the twelve repository: rows point outside Zoo. ZIPs 0400, 0403, 0408, 0411, 0412, 0413, 0415 and 0422 name hanzoai/* or zenlm/* repositories. Three of those are Rust or Go — hanzoai/search, hanzoai/mcp, hanzoai/zen — and could be graded by an audit of the Hanzo estate. Grading Zoo for code in another organisation's repository would be wrong whichever way it came out.

All twelve repository: URLs do resolve, which is a change from the state LLM.md warns about. One repository-shaped claim outside the frontmatter does not: zip-0005:275 gives zooai/pqc, and gh repo view returns Could not resolve to a Repository.

ZIP-0810 (Z-Chain). Rust is genuinely the right runtime for the Plonky3 STARK prover it describes, but the ZIP delegates to luxfi/plonky3-pq and marks it planned at line 110. The place to look is the Lux estate.

No C++ exists. A search for *.cpp, *.cc, *.cxx and CMakeLists.txt across ~/work/zoo returns nothing. The 134,387 lines under wallet and 2,303 under yapp are .h only — React Native and iOS bridging headers from a Uniswap fork, and a vendored Sparkle.framework. There are no C++ verdicts to give, and the C++ row above is empty for that reason rather than by omission.

One row that collides with the index's own check

scripts/index.py:126 refuses to write the README when a Final ZIP carries implementation-go: none, on the ground that Final and none are two claims about one body of code and one of them is wrong. Exactly one row here trips it:

go:0803  none   ZIP-0803, Encrypted Streaming Replication, status Final

Applying it means first deciding whether ZIP-0803 is really Final. The search was: luxfi/replicate, zapdb-replicator and ghcr.io/zoolabs/replicate across every yaml, Dockerfile and .go under ~/work/zoo — zero hits, against a ZIP that names three upstream Go sidecars at lines 272–274. The other four none rows are on Draft proposals and raise no such contradiction.

The Go story is nine thousand lines of import lists

Zoo's Go across ten repositories is 9,538 lines, and none of it implements a cryptographic, consensus or DEX primitive. ML-DSA, ML-KEM, SLH-DSA, Corona, Pulsar, FROST, CGGMP21, FHE, the AI and inference precompiles and the DEX VM all arrive as blank imports of github.com/luxfi/precompile/* at published versions — node/vm/factory.go and chains/zoo-evm/main.go are, between them, mostly an import block. No repository carries a replace directive; the one in node/go.mod:278 is commented out.

That is a defensible engineering posture: Zoo consumes Lux as a dependency rather than forking it. But it means "implemented in Go" is true of almost no ZIP in the sense the field asks about, which is why every Go verdict above is partial or none and none is shipped. What Zoo's Go decides is which primitives to link and what the genesis says.

The node binary and the EVM plugin disagree about post-quantum finality

chains/zoo-evm/main.go:56 registers luxfi/precompile/pulsar at 0x012204. node/vm/factory.go never imports it — grep returns zero. ZIP-0812 pins Pulsar-M-65 as the primitive that ZIP-0811's Q-Chain finality consumes, so the artifact an operator actually runs is missing the primitive the mirror ZIPs depend on, while a sibling plugin has it.

ZIP-0811 compounds this by naming a VM at zooai/node/chains/quasarvm. That path does not exist; zoo/node has no chains/ directory at all, and zooai/chains ships quantumvm under the upstream module path github.com/luxfi/chains/quantumvm/plugin.

zooai/node holds two unrelated projects under one name

The repository contains a 2,732-line Go L1 node and a 553,327-line Rust AI agent node, side by side. The Rust half splits into hanzo-libs (248,750 lines), hanzo-bin (96,111), zoo-libs (125,390) and zoo-bin (81,450), and zoo-libs is a name-for-name fork of hanzo-libs: zoo-fs and hanzo-fs have identical file counts and byte-identical sources modulo the string substitution. zoo-libs is the older snapshot — it still carries the pre-rename Shinkai crate names (crypto-identities, message-primitives, tools-primitives, sqlite) while hanzo-libs has since gained 33 crates it never got. Retained LICENSE files under hanzo-tools-runner and hanzo-runner show the same lineage, and app/apps/zoo-desktop/src-tauri/src/galxe.rs survives untouched from the Shinkai desktop application.

The most substantial original Rust in the estate has no ZIP

zoo/operator is 2,014 lines carrying four working CRDs — ZooNetwork, ZooChain, ZooExplorer and ZooGateway under group zoo.network/v1alpha1 — a 919-line controller and a leader elector, built on hanzoai/operator-core. No ZIP describes it. Meanwhile ZIP-0014's KMS integration is four lines of Dockerfile with a main.go that prints instructions instead of following them, and ZIP-0015 is Final asserting L2 while node/main.go:4 and evm/main.go:4 both call the same binary a sovereign L1 and zip-0036:53 records the Zoo EVM as not bootstrapped. The corpus and the code are miscalibrated in both directions at once.