Breadslice 1 — 39
For the Mina team · Concept

Mina as the trust anchor for complex TEE architectures.

Why the coming wave of confidential cloud apps needs a light client with the certainty of a full node, and why only Mina has one.

2 · Adoption 2 — 39
Confidential computing as a share of cloud spend

The percentage of cloud spend on confidential compute (TEEs) is to quadruple by 2030, hitting $154B.

Same metric and sources for both years. Confidential computing: Grand View Research ($18.1 B 2026, $153.8 B 2030). Cloud: Goldman Sachs Research ($2 T by 2030, 22% CAGR; 2026 derived). Blue area to scale. A spend proxy, not a workload count.

3 · Why now 3 — 39
What is pushing this

Four forces, arriving together.

01

A general move to hardened, attestable software

The vulnerability apocalypse is said to be arriving. The harder your system the better; TEEs force system hardening by means of verifiable integrity.

02

A maturing understanding of what a TEE in a hyperscaler data center constitutes

Location means something. Same chip, but a TEE located in your basement is a side-channel liability; a TEE provably located in a hyperscaler data center is a proper trust boundary.

03

Rise of AI-assisted attestation verification

An attestation is only as good as someone reading the attested code. AI agents can now review entire TEE codebases at speed, and with languages like Rust the reproducible build can be done quickly and deterministically.

04

Private AI inference

People hand AI their most sensitive data. This single workload will account for tens of billions in increased spend on TEEs.

4 · The shift 4 — 39
The next few years

Hyperscaler offerings are mature.

Every hyperscaler now ships a production confidential-compute offering, with years of hardening and long lists of case studies.

Google Cloud
Confidential Space

Attested container workloads; the image digest is the trust anchor.

AWS
Nitro Enclaves

Isolated enclaves attested by PCR measurements of the enclave image.

Azure
Intel TDX confidential VMs

Whole VMs isolated from the host and hypervisor, with hardware attestation.

5 · Evidence 5 — 39
Built for TEEs from day one

Newer products are designed from the start to work in TEEs.

Example: Meta’s Muse, a personal AI agent announced September 2026, with Signal creator Moxie Marlinspike involved.

Today
Muse Secure VM

A dedicated VM per user. A Sentinel agent gatekeeps all outbound network traffic.

→
Next
Muse Confidential VM

The entire VM encrypted with a key held only by the user. Meta removes itself from the trust equation.

Source: Forkast, “When the building owner doesn’t have the key: Meta’s Muse, confidential VM and the third trust architecture” (Sep 2026).

6 · Consequence 6 — 39
What follows

As a result, TEE ecosystems will be more complex and more demanding.

Many different TEEs doing different jobs, working together through complex modes of orchestration.

KEY-RELEASE TEE heart of the ecosystem OIOO TEE opt-in / opt-out APP WORKER AI INFERENCE DATA STORE MESSAGE RELAY USER-DATA VAULT
7 · Mina’s role 7 — 39
Where Mina comes in

Mina has a critical role to play in TEE-based services that handle orchestration for the wider TEE ecosystem.

Two service examples:

01 · PUID
Post-update key distribution
+
02 · OIOO
Opt-in / opt-out
8 — 39
Component 1

PUID in TEE

Post-update key distributor

Releases keys to other TEEs after their code is updated, once the update is proven approved.

9 · Key-release TEEs 9 — 39
Component 1 · Key-release TEEs

The heart of the ecosystem: TEEs that release keys to other TEEs after code updates.

TEE Group X is updated, and each TEE in the group needs the keys the pre-update TEE Group had.

01

Rarely updated

The code for the image of the key-release TEE must be rock hard and updated infrequently. TEEs around it can change often, but it does not.

02

Needs the outside world

Must have trusted communication with the outside world to know a release is allowed.

03

Immune to host forgery

The host of a TEE controls every byte in and out. The TEE must be 100% immune to any attempt from a malicious host with total control of the pipe.

10 · The options 10 — 39
How does a TEE read the chain?

Mina solves this with full-node certainty in a long-lived, TEE-sized package.

Full nodeOther light clientsMina light client
Small enough for a TEE✕✓✓
Full-node certainty✓✕✓
“Refresh-proof” trust anchor✓✕✓
Rarely needs updating✕✕✓
11 · How it works 11 — 39
The Mina light client inside a key-release TEE

Provisioned once. No update until a hard fork.

01 · PROVISION
Hard-fork genesis

Baked into the image. That is the only trust input.

→
02 · FETCH
Latest SNARK

Pulled through the untrusted host.

→
03 · VERIFY
Chain proof

One recursive proof covers the chain back to genesis.

→
04 · READ
zkApp state

Merkle path against the snarked ledger, e.g. the approved code hash of a new TEE.

→
05 · ACT
Release the key

Only to attested code whose hash matches.

12 · Built 12 — 39
Not a thought experiment

We’ve built and tested it.

Full overview of our test build in the appendix.

Footprint
8MB

A Rust light client, small enough to measure and ship inside the TEE image.

Wire
binprot

Speaks Mina’s native binprot encoding directly.

Result
State.

Runs, fetches and verifies zkApp state end to end.

13 · Comparison 13 — 39
Light clients, side by side

No other light client verifier at this level.

Other light clientsMina light client
Trust anchor lifetimeGoes out of date after a short time (weak-subjectivity windows, rotating committees). Must constantly cycle or hit bootstrap problems.Valid until the next hard fork, set and forget.
Basis of trustTrusted parties signing: consensus / committee signatures, honest-majority assumption.Cryptographic proof via the snarked ledger.
Verification workFollow headers and every validator-set change since the anchor.One constant-size proof, however long the TEE was offline.
A lying host can…Exploit a stale anchor, feed a minority fork, or stall bootstrap.Only withhold or delay. Liveness, never safety.
Updates to the TEETrack forks, committee and client changes, with frequent re-measurement.Hard forks only. Fits a rarely-updated key-release TEE.
Security vs a full nodeStrictly weaker.Equivalent cryptographic strength.
14 — 39
Component 2

OIOO in TEE

Opt-in / opt-out orchestration

Carries each user’s decision on an update to every TEE that holds their data.

15 · Context 15 — 39
Context

The nature of TEE-ecosystem updates is changing.

AI has advanced to the point where individual corporate users of applications running in TEE ecosystems can use their AI agents to review code updates, and decide to remain in the ecosystem or not before the update takes place.

The past
Attestation mostly theatre

The host can update the code at any time. When an update hits, whatever attested code your IT team reviewed on signing the contract is invalid. (And the team are not going to do a review again!)

→
The present
Every update attested

Your agents attest every proposed update in the background. You have a verifiable, credible exit before the update hits, for example if the agent detects a meaningful change in security posture.

16 · OIOO TEEs 16 — 39
Component 2 · Opt-in / opt-out TEEs

Every user gets a private vote on every update.

Individual users’ agents read the new code at speed and decide whether the update is acceptable to them.

01
Update proposed on chain

New code hash published for review.

→
02
User’s agent reviews

AI reads the diff against the user’s own policy.

→
03
Opt in or out

Not okay? Opt out (or simply don’t opt in).

→
04
OIOO TEE propagates

Tells every TEE holding that user’s private data.

→
05
Wiped pre-update

The user’s data never reaches code they rejected.

17 · Approving updates 17 — 39
Mina on the update side too

This is essentially Mina’s existing ZK voting tech, except you’re not privately voting for the president, you’re privately voting for a software update.

Flexible
Any rule

Admins, quorums, time-locks, per-user opt-outs, expressed as zkApp logic.

Private
No signatures

Approvals are proofs, not signatures. Who approved can stay private.

Recursive
One zkApp

Thousands of individual decisions fold into a single state the key-release TEE reads in one step.

18 · Same light client 18 — 39
Reading the votes

The light client properties that enabled trusted communication with the outside world for key release are the same for vote processing.

01

Host cannot forge votes

02

Long-lived trust anchor

03

Cryptographic security of a node

19 · Topology 19 — 39
Deployment

Key release and OIOO: one TEE or two.

Combined
One TEE does both

Reads the approved code hash and the per-user opt-outs from the same Mina state, then releases keys accordingly.

or
Separate
Two specialised TEEs

Each stays smaller and simpler. Both anchor to the same Mina light client pattern.

20 · Why Mina fits 20 — 39
Properties of Mina

Four Mina-specific properties, each doing real work.

General propertyPractical implication of the general property for this use case
SuccinctnessA long-lasting trust anchor and full-node security in 8 MB of Rust.
RecursionCompresses the overall vote state into a single artefact without the need to reference or cross-check.
General ZKUsers can agree to remain users of the application or credibly exit without revealing they were or are using it.
TypeScriptKey parts of the opt-in / opt-out flow can be browser-based, allowing for widespread implementation.
21 — 39
The thesis

A genuine killer use case for Mina on paper. What remains is go to market.

Every complex TEE ecosystem needs this, or something like it. The question is mainly one of productisation and promotion.

22 — 39
Appendix 1 · What we built

A TEE-based Mina light client verifier in 8 MB of Rust.

Full-node certainty about Mina state from one constant-size proof. Runs inside a TEE, trusts nothing but its own embedded anchors, and verifies today’s post-Mesa mainnet.

23 · Overview 23 — 39
At a glance

Small, self-contained, tested on live mainnet.

Footprint
8MB

One wasm32-wasip2 component (8,221,817 B), of which 4.6 MB is Mina’s public SRS, embedded.

Language
Rust

~3,000 lines of our own code on top of o1-labs’ pickles verifier and openmina’s wire types.

Memory
~90MB

Peak RAM of the wasmtime process during a verify (~72 MB settled). RAM-only: no disk, no sidecar.

Verify
1.3s

One post-Mesa block verified at native speed.

24 · Built from 24 — 39
What we took, what we didn’t

From openmina we took the vocabulary, not the node.

Pulled in from openmina
  • mina-p2p-messages: the binprot wire types (block header, accounts, RPCs)
  • mina-tree hashing only: Poseidon protocol-state hash, account leaf hash, merkle path types
  • poseidon parameter tables
  • libp2p RPC transport: native builds only, never in the wasm
Left behind
  • mina-tree::proofs: openmina’s block verifier, ~27k lines
  • Node state machine, consensus, transition frontier
  • Ledger storage, snark workers, prover
  • openmina’s patched proof-systems fork

Of mina-tree’s ~79k lines, we use the hashing and account types.

Replaced with
  • o1-labs pickles-verifier: ~2k lines, no_std, from o1js-to-zkvm
  • proof-systems (kimchi) on the Mesa gate set
  • Our ~3k lines: header→proof shim, merkle walk, V3 leaf hash, verifier wrapper

v1 used openmina’s verifier; v2 swapped it out. That swap is what made Mesa fixable.

25 · The OCaml node 25 — 39
What came from a running OCaml node

No OCaml code in the client. A node is only a data source.

At build time · once
The verification key

Read from the daemon’s blockchainVerificationKey and spliced into kimchi’s format. Cross-checked byte-for-byte against an independent copy (28/28 commitments).

At build time · once
Genesis & fixtures

The fork-genesis state hash, chain id and captured headers for offline tests. Publicly checkable against any explorer.

At runtime · untrusted
Snarked account + merkle path

Our patched daemon serves the account bytes and a 35-level path from the snarked ledger. Stock nodes don’t expose these. Every byte is checked against the verified header.

The block header itself can come from any Mina peer. Our latest test used a public mainnet seed.

26 · Provisioned at start 26 — 39
Baked into the image · the only trust inputs

Three anchors. No validator sets, no checkpoints, no expiry.

Anchor 1
Fork-genesis state hash

Every verified block must cite it. Post-Mesa mainnet genesis, block #548,147.

3NLntCRR9RvjtzP24Q1dRvdhmpjiPvfKGaJmAZuJgYoqGpevqDR7
Anchor 2
Blockchain verification key

The wrap-circuit VK: 3.6 KB, 28 curve-point commitments. Identifies which circuit a proof must satisfy.

sigma_comm[0] = a0a97904…1e2180
Anchor 3
SRS + verifier code

Public parameters (Pallas + Vesta, 4.6 MB) and the gate definitions. Embedded, so they sit inside the measured wasm hash.

pallas.srs + vesta.srs · 2 × 2.29 MB

Config, not trust: libp2p chain id 0718f61a… (only keys the peer handshake), and finality depth k = 290. The app’s own anchor, the zkApp, is next. Chain anchors change only at a hard fork; the last was Mesa, 3 Sep 2026.

27 · Burned-in zkApp 27 — 39
Anchor 4 · the application

A burned-in zkApp: it reads one contract.

A merkle proof shows an account is in the ledger, not that it’s ours. So the zkApp’s identity is compiled in next to the chain anchors, inside the measured hash.

Which account
Address

The zkApp’s public key.

B62qirEk…ATSnEHsLmPz
Exactly one
Token

Default MINA token, so the address maps to a single account.

token id 1 (MINA)
Which logic
Contract VK hash

The verification key of the contract allowed to hold this state.

21666817…16743727
Who may write
editState rule

Pin Proof so only the contract can change state. Our test zkApp uses Signature (owner key).

test: Signature · prod: Proof
Sent in afterwards · untrusted

Headers, the account bytes and its 35-level merkle path, the node’s URL. Each is checked against what is already burned in.

Why it matters

Without the pin, a lying node can return any other real account and its merkle proof passes. Found in the June build; fixed and covered by five tests.

28 · One-way door 28 — 39
Irrevocable key-release policy · illustrative

A commit is a one-way door.

ReleasePolicy zkApp · on-chain state

Approved reference values for a mixed TEE fleet. Stored as hi/lo field pairs; the zkApp enforces the state transitions.

[0]policy_epoch42
[1]statusCOMMITTED  (write-once latch)
[2]committed_atblock 556,412
[3–4]gcp_cs.image_digestsha256:9c1e4f…7b0a4b7a
[5–6]aws_nitro.pcr0sha384:5a0d83…e1c2f9d6
[7–8]intel_tdx.mrtdsha384:b41f07…3d9e06a2
[9]timelock_untilblock 556,040  (review window)

Transitions are proof-authorised (editState = Proof): the circuit only allows PROPOSED → COMMITTED, never back.

Lifecycle of one policy epoch
Proposeepoch 42

New measurements published as PROPOSED. Nothing is released.

Review windowtimelock

Auditors, AI review and opt-outs act here. The only place to stop it.

Committ = 0

Status latches to COMMITTED. The contract cannot unset it.

Final+18.8 h · 290 blocks

Consensus-final: no reorg can remove the commit.

POINT OF NO RETURN
Light client learns~+24 h · proven

The key-release TEE verifies the commit against the snarked ledger.

Secure key release

Keys go to workloads whose attestation evidence matches the reference values.

Once final, key release cannot be recalled. The ~24 h before the TEE sees it is delivery latency, not a cancellation window.

Revocation only blocks future releases (a new epoch that drops the reference value); keys already released stay released. Values shown are illustrative.

29 · Why state fields 29 — 39
zkApp design · what the TEE can actually prove

The policy lives in state fields, not actions or events.

State fieldsActionsEvents
Where it livesIn the zkApp account, a leaf of the ledgerData on archive nodes; the account keeps only a rolling hash (action_state)Archive nodes only; never in the ledger
Light-client proof✓ One merkle path to the proven snarked rootNeeds the full untrusted list, re-hashed, plus the reduce logic✕ Nothing on-chain to check against
Takes effectWhen the transaction is appliedOnly after a later reduce transaction folds it into stateNever: a log, not state
Capacity32 fields since Mesa; one field can hold a merkle root for moreUnbounded queueUnbounded log
Best forFew, deliberate writes the TEE must trust: a release policyMany concurrent writers, e.g. per-user opt-in/opt-out votesIndexing and UI history

Actions can feed the zkApp, events only log it. State is what the TEE trusts.

Many-writer flows (opt-in/opt-out) dispatch actions, a reducer folds them into a state-field root, and the key-release TEE reads that root, never the actions themselves.

30 · How it works 30 — 39
One read, end to end · as run in our tests

Two things come from outside. Everything else is checked inside the TEE.

01 · FETCH
Best-tip header + its SNARK

From any Mina peer. 12.7 KB of binprot, of which ~11 KB is the chain proof.

passed in from outside
02 · DECODE
Binprot → header

Exact wire types from openmina’s p2p-messages.

inside the TEE
03 · ANCHOR
Genesis check

Header must cite the embedded fork-genesis hash.

inside the TEE
04 · HASH
Protocol-state hash

We compute it ourselves; it becomes the proof’s public input.

inside the TEE
05 · VERIFY
Pickles proof

Accumulator check + kimchi opening. One proof covers the chain back to genesis.

inside the TEE
06 · EXTRACT
Snarked ledger root

ledger_proof_statement.target, now proven, not claimed.

inside the TEE
07 · FETCH
Account + merkle path

Account binprot and 35 sibling hashes from a node.

passed in from outside
08 · READ
Check it, then read

It must be the burned-in zkApp, and its merkle path must reach step 06’s root. Then read its state.

inside the TEE
31 · When can it be read? 31 — 39
One zkApp state update, written now · Mesa mainnet · 3.9 min blocks · ~370 blocks/day

Scan state determines time of read. Transaction volume determines time of scan state.

now+6 h+12 h+18 h+24 h+30 h+36 h+42 h+48 h CHAIN~370 blocks/day ① WRITTEN NOW 48 h ~900 user txns/day1.3× today SCAN STATE · PROVEN +48 h ✓ +48 h 24 h ~2,400 user txns/day3.5× today SCAN STATE · PROVEN +24 h ✓ READABLE FROM +24 h 12 h ~5,500 user txns/day8× today SCAN STATE · PROVEN +12 h Extra wait to hit290 blocks ✓ READABLE FROM +18.8 h

Readable = proven and final. The scan-state wait shrinks as network volume grows; finality is fixed at 290 blocks. Below ~18.8 h of scan state, the 290 blocks become the wait (the 12 h row). Today’s ~700 user txns/day gives ~55 h. Volumes include ~1.7 coinbase/fee transfers per block.

32 · Catch-up times 32 — 39
State change → readable by the light client

Mesa cut the wait by a third. Volume cuts the rest.

tip read (our patch)+ k-leg → root read (stock node)pre-Mesa, measured
June 2026 · pre-Mesameasured · ~700 user txns/day
84 h121 h
Mesa · today’s volume~700 user txns/day · 1×
55 h  / 74 h
Mesa · 1,200 txns/day1.7×
40 h  / 59 h
Mesa · 2,400 txns/day3.5× · our 24 h budget
24 h  / 43 h
Mesa · 3,100 txns/day4.4×
20 h  / 39 h
Mesa · 5,500 txns/day8×
12 h  / 31 h

Model: lag ≈ 24 trees × 128 txns ÷ txns per hour (matched June’s measurement within 1%). Mesa halved slot time (180 s → 90 s); the scan state is unchanged. Mesa rows are estimates at 3.9 min blocks; the June row was measured on a real zkApp write.

33 · The ceiling 33 — 39
How far volume can take it

Our 24 h target needs ~5% of mainnet’s capacity.

Per block
128 txns

27 scan-state slots, shared with coinbase and fee transfers → ~126 user txns.

Per day today
~370 blocks

90 s slots, 39% filled → a ceiling of ~46,700 user txns/day (~0.5 TPS).

zkApp limit
12 per block

Mesa halved it. ~4,400 zkApp commands/day today, the real bottleneck for zkApp-heavy volume.

Floor
~1.5 h

Tip-read lag at full blocks (24 blocks). The root read never beats ~20 h; the k-leg is fixed.

Plain payments are the cheap way to fill the pipeline: ~1,700 extra txns/day reaches 24 h. Either way, no IT team is signing off on an update before 24 hours, agents or no agents.

34 · Binprot 34 — 39
How the wire format works

Binprot read in Rust.

On the wire
a1 01 08 41 f6 28 57 f9 …

12,717 bytes. Fields back to back, no names or tags. First bytes of block #556,001 from a mainnet seed.

→
Decoded in Rust · MinaBlockHeaderStableV2
protocol_statewhat we hash
protocol_state_proof≈ 11.1 KB recursive Pickles proof
delta_block_chain_proof
current_protocol_version
proposed_protocol_version_opt
Integers

0x00–0x7f is the value itself (1 byte). 0xfe/0xfd/0xfc prefix a 2/4/8-byte value.

Records

Fields in type-definition order, no names, no lengths. Decoding needs the exact type.

Options & variants

One tag byte (00 = None, 01 = Some …), then the payload.

Field elements

32-byte little-endian integers. Lists are a length, then items.

35 · Why binprot 35 — 39
Why not just use GraphQL?

To check the proof, you must hash exactly what consensus hashed.

GraphQL · lossy
A friendly view, not the data
  • Missing: ledger_proof_statement, sub_window_densities, the consensus constants, genesis_ledger_hash
  • Reshaped: staged-ledger hash flattened to strings, public keys as base58
  • Fine to fetch a proof, but the state hash must then be taken on trust
Binprot · exact
The bytes nodes gossip
  • Every field of the protocol state, so we compute the state hash ourselves
  • Ledger roots come out of the verified header, not a node’s claim
  • Versioned types (Stable.V2 → V3); the Mesa header stayed byte-compatible

Tested: flip one byte of the header’s protocol state and verification fails.

36 · Mesa 36 — 39
The hard fork of 3 Sep 2026

Mesa changed the verifier itself. We found why, and fixed it.

May 2026 · the wall
Every input correct, final check fails

On the Mesa testnet: VK, state hash, proof shape, accumulator all matched. Eight hypotheses ruled out; the kimchi opening check still rejected.

Root cause
A gate changed

proof-systems #3514: the EndoSclMul gate went from 11 to 12 constraints, shipped with Mesa. Our verifier checked the old gate.

Sep 2026 · fixed
New gate + new anchors

Mesa-gate proof-systems, VK spliced from mainnet (2 of 28 commitments differ from testnet), fork-genesis hash. Post-Mesa mainnet verifies.

Lesson: a hard fork can change the verifier code, not just the key, which is why anchors are re-measured only at hard forks.

37 · Test log 37 — 39
What we have actually run

From first verify to post-Mesa mainnet.

DateNetworkWhatResult
2026-05-22Mainnet (pre-Mesa)v1 (openmina verifier), header over libp2p✓ 442 ms native
2026-05-22Mesa testnetv1 on Mesa blocks; zkApp V3 decode + inclusion✕ OpenProof
2026-06-12Mainnet (pre-Mesa)v2 inside wasmtime, RAM-only✓ 18 s M1 · 85 s e2-small
2026-06-13Mainnet (pre-Mesa)Merkle inclusion against the snarked root✓ root matched
2026-06-14Mainnet (pre-Mesa)zkApp write → snarked read, tip-materialisation patch✓ after ~84 h
2026-09-24Mainnet (post-Mesa)Mesa gate + new anchors; header from a public seed✓ #556,001 in 1.3 s
2026-09-24Mainnet (post-Mesa)Rebuilt 8 MB wasm (zkApp burned in), verified inside wasmtime✓ 26 s · ~90 MB
2026-09-24LibraryBurned-in zkApp: wrong address, token, contract or write rule✓ all rejected
2026-09-24Mainnet (post-Mesa)Controls: tampered header, altered state hash, pre-fork proof, June image on the new chain✓ all rejected
38 · Trust model 38 — 39
Against a host that lies

The host can delay the answer. It cannot forge it.

A lying host or node can
  • Withhold the header, or serve an old one, caught by the freshness check on the header’s own chain timestamp
  • Refuse to serve an account or path
  • Stall a CPU-bound verify (liveness only)
It cannot
  • Make a block verify on a different genesis or circuit
  • Change any protocol-state field without breaking the proof
  • Serve a false account value: the merkle walk must hit the proven snarked root
  • Swap in a different real account: the burned-in zkApp identity must match

The public mainnet seed, minascan GraphQL and our patched OCaml daemon are all untrusted in this design; each was used as a source in testing.

39 — 39

Thank you.

joe@breadslice.com