# Why We Run Zakura on Different CPUs and Compilers

Engineering post by Roman Akhtariev about how Zakura can run nodes on
different CPU architectures and compiler backends: a node whose build
shares as little as possible with the regular nodes, so that compiler and
CPU-specific bugs show up as disagreements instead of hiding behind identical
builds.

What the post says:

- Compilers can make correct code produce the wrong result. Zakura nodes
  running the same build share any miscompilation, so their agreement may not
  surface a low-level, platform-specific bug baked into every binary.
- Regular Zakura nodes run Linux on x86-64, compiled with LLVM. The new node
  runs on an ARM64 Mac, compiled with Cranelift. Monitoring compares
  their results and makes any disagreement visible within minutes.
- Building a Rust program has two stages: a shared first stage (the rustc
  front end) that checks the code and lowers it to an intermediate form, and
  a backend that emits machine instructions. Cranelift is a separate,
  independently written backend. The post includes a figure of the pipeline:
  one source tree, the shared front end, the LLVM x86-64 and Cranelift ARM64
  paths, and the monitoring comparison both builds feed.
- Some libraries contain separate implementations for different processors,
  selected at compile time or through runtime feature detection, so changing
  architectures can change both the generated instructions and the library
  routines that execute. The post's example: a hashing or large-integer
  arithmetic library might select an AVX2 or AVX-512 routine on x86-64 and a
  NEON routine on ARM64; a defect in the x86-only variant never runs on the
  Mac.
- A bug in LLVM's translation or in an x86-only routine therefore will not
  repeat on the Mac node. When the nodes disagree, those two
  layers are the first place to look.
- Some layers remain shared: both builds use the same first stage, Cranelift
  compiles only Rust, and Zakura's C dependencies and the operating system's
  libraries are built with their usual compilers on each platform. Bugs there
  affect both builds.
- Example of an architecture-specific code path: OpenSSL's CVE-2026-28386
  (April 2026) was an out-of-bounds read in its AVX-512/VAES implementation
  of AES-CFB128; other architectures used unaffected implementations.
  OpenSSL rated it low severity. The post cites it to illustrate why
  architecture diversity matters: the ARM build never executes the faulty
  routine.
- The more dangerous case is a miscompiled verifier on the x86 build that
  accepts a proof claiming to spend a note that never existed. Every node
  running that build would accept a counterfeit-value transaction and agree
  with each other. Zcash's turnstile (ZIP 209) caps the damage at the pool's
  balance, but the counterfeit becomes a claim on real users' funds, so the
  post stresses detecting such a bug immediately rather than when the pool is
  drained. A Cranelift ARM64 node that does not share the bug would reject
  the block containing it and stop advancing; the monitor flags the stall
  within minutes.
- An arithmetic error such as a dropped carry while hashing a commitment tree
  rejects no block: both nodes keep advancing but compute different tree
  roots.
- The monitor continuously compares committed results at corresponding block
  heights, a few blocks behind the shortest chain tip across all nodes: block hashes and the
  roots and frontiers of the Sapling, Orchard, and Ironwood commitment trees.
  The dropped carry produces a tree mismatch at a height both nodes have
  reached and is flagged immediately; a proof only one build rejects leaves no
  matching height to compare (the Cranelift node stops while the LLVM node
  moves on), and the stall is flagged after a few minutes. The post does not
  describe an on-call or paging setup; do not add one.
- Limits: the check only catches bugs that are exercised and produce
  different observable results. Bugs in shared source or protocol design run
  the same way on both builds; Bitcoin's 2018 inflation bug (CVE-2018-17144)
  was of that kind, so no build would have disagreed. The diversity check is
  one more way to catch problems sooner, alongside testing and review, not a
  replacement.
- The post closes by framing build diversity as one instance of a broader
  pattern: a failure every node shares is a failure no node can witness, so
  reducing what the whole fleet has in common turns more bug classes into
  visible disagreement. Independent implementations of the verification
  logic are named as a direction that principle extends to, not as a shipped
  or committed project. Do not represent an independent verifier
  implementation as existing or scheduled.

Sources linked from the post:

- OpenSSL advisory: https://openssl-library.org/news/secadv/20260407.txt
- ZIP 209: https://zips.z.cash/zip-0209
- Bitcoin Core CVE-2018-17144 notice:
  https://bitcoincore.org/en/2018/09/20/notice/

---

Canonical HTML version: https://zakura.com/engineering/cpu-compiler-diversity/
