MLXDocs
Integrity

Witnesses

Markdown

Macs running MLX Node 0.9.7 or later check every new checkpoint against the last one they cosigned and sign it with their Secure Enclave key, so a split view would have to fool every one of them.

What a witness Mac does

Witnessing is built into MLX Node from version 0.9.7 and runs on its own while MLX Node is open (Core/Witness.swift):

  1. Pin the keys. The first time, it remembers the sequencer's public key and the Solana anchor account from GET /api/log. If mlx.app later signs with another sequencer key, it flags it.
  2. Fetch and verify. Periodically it fetches GET /api/log/checkpoint and verifies the signature with the pinned key (Checkpoints).
  3. Compare with what it cosigned last. It keeps only the newest checkpoint it cosigned.
    • A smaller size than that one, or the same size with a different root: evidence of a rewrite.
    • A larger size: it asks for a consistency proof from its size to the new one and verifies it (Proofs). A proof that fails is evidence too.
  4. Cosign. If everything holds, it signs the checkpoint with the Mac's Secure Enclave key and posts the cosignature.
  5. Check the anchor. About once an hour it reads the newest anchor memo straight from Solana's public RPC (not through mlx.app) and checks it is consistent with the checkpoint it cosigned (Anchors).

When something doesn't add up, MLX Node saves both signed notes as evidence in its Application Support folder and shows "Inconsistency found" in Settings → Ledger witness, with a button to show the evidence. Otherwise that row says "Witnessing the MLX ledger" and what it checked last.

The cosignature

A cosignature says: as of time t, this is the newest consistent checkpoint I have seen. The Mac signs this text (cosignMessage in lib/chain/tlog.ts):

What a witness signs
mlx-cosignature/v1
time 1793116011
mlx.app/ledger/mlx-1
398
y5euvUWfr1GfTZZ9W2qY+v/y3w9qaB9L+J00VgslPX4=

That is mlx-cosignature/v1, then time <Unix seconds>, then the checkpoint's body (its first three lines, each ending in \n). The signature is ECDSA P-256 over SHA-256 of that text, with the Mac's device key, as raw r‖s (128 hex characters).

Post a cosignature

POSThttps://mlx.app/api/log/cosign

Device-signed like every request a Mac makes: the header x-mlx-device carries <device public key>|<ms>|<signature> over the request (Worker protocol). Each signed request is accepted once.

ParameterTypeNotes
sizeintegerThe size of the checkpoint being cosigned. It must be a checkpoint the log signed.
timeintegerThe time in the signed text, Unix seconds, close to the server's clock.
sigstringThe P-256 signature over the cosignature text, raw r‖s hex.
Request body
{ "size": 398, "time": 1793116011, "sig": "<128 hex characters>" }
Response
{ "ok": true, "size": 398 }

The server keeps one cosignature per Mac per checkpoint, and remembers the largest size each Mac cosigned.

StatusBodyWhen
400{"error":"Bad cosignature"}size, time or sig malformed.
400{"error":"Clock is off"}time too far from the server's clock.
401{"error":"Unsigned request"}, {"error":"Bad signature"}The x-mlx-device header is missing or doesn't verify, or its time is too far from the server's clock.
403{"error":"Signature doesn't match"}sig doesn't verify for this device over this checkpoint.
404{"error":"No checkpoint of that size"}The log never signed a checkpoint of that size.
409{"error":"Older than your last cosignature","last":<size>}This Mac already cosigned a larger size: a witness never goes back.
409{"error":"Request already used"}The same signed request was sent twice.
429{"error":"Slow down"}Too many cosignatures from this Mac in a minute.

Who has cosigned

GET /api/log lists the Macs that cosigned the newest checkpoint under witnesses, each with an opaque id (derived from its device key; the same id MLX World uses) and the time it signed:

From GET /api/log (trimmed)
"witnesses": [
  { "id": "2b372dd759bf0d89", "time": 1793116011 },
  { "id": "9547fd72c3308a3d", "time": 1793116266 }
]

The cosignatures themselves and the witnesses' keys are not published, and any device key can post one; a Mac doesn't have to be linked to a wallet. Witnesses can therefore be the operator's own Macs: what they add is that every honest one would have caught a rewrite it was shown. Independent outside witnesses are planned.

Run a witness

Install MLX Node 0.9.7 or later and leave it open; nothing to turn on. A witness Mac doesn't need a dedicated seat. To witness without a Mac, do what it does in your own code: keep the last checkpoint you verified, check every new one with a consistency proof (Checkpoints), and compare it with the Solana anchors.