Anchors
The log root and the state root are written to Solana every hour and timestamped on Bitcoin every day, so a checkpoint can be checked against public chains the operator can't edit.
Why anchors
A checkpoint you saved protects you; an anchor protects everyone. Once a log root is on Solana or Bitcoin, the sequencer can't later show anyone a history that doesn't extend it, because a consistency proof from the anchored size would fail. Both anchors are sent by the produce job (lib/chain/anchor.ts), only when the checkpoint or the state commitment has changed since the last one.
Solana memos
At most once an hour the anchor account sends a Solana transaction with one Memo program instruction:
| Anchor account | AeWxrwqF51Ln4xzNZeccR1J4WiaNAkG9rj6XcsHTJTgJ |
| Memo program | MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr |
| Memo text | <chain> log <size> <log root> state <height> <state root> usdc <total> |
mlx-1 log 398 cb97aebd459faf519f4d967d5b6a98fafff2df0f6a681f4bf89d34560b253d7e state 394 0cc077af7c40681c5a24702c0e71bed5c67333af42f1f4f16317a2123fd88f63 usdc 11285277511The log part is the newest checkpoint; the state part is the newest state commitment at that moment, which may be a few blocks older (state is committed at most hourly). Before the first commitment the memo has only the log part.
The anchor account's key is derived from the sequencer's secret, so only the sequencer can write from it. It pays the Solana fee from its own SOL; when it runs low, anchoring pauses and GET /api/log shows anchorStatus.solana: "waiting for SOL".
Read the memos from Solana yourself
Ask any Solana RPC, not mlx.app:
curl https://api.mainnet-beta.solana.com -H 'content-type: application/json' -d '{
"jsonrpc": "2.0", "id": 1, "method": "getSignaturesForAddress",
"params": ["AeWxrwqF51Ln4xzNZeccR1J4WiaNAkG9rj6XcsHTJTgJ", { "limit": 1 }]
}'{
"jsonrpc": "2.0",
"result": [
{
"blockTime": 1793115364,
"confirmationStatus": "finalized",
"err": null,
"memo": "[170] mlx-1 log 398 cb97aebd459faf519f4d967d5b6a98fafff2df0f6a681f4bf89d34560b253d7e state 394 0cc077af7c40681c5a24702c0e71bed5c67333af42f1f4f16317a2123fd88f63 usdc 11285277511",
"signature": "4oShU8RoQKw9BQr1yY2cFAm2go5tBeagcgxeouzZ1rD9U68GdTnr7fN9LPY5GFw3zwysWrtYXnBEKBssb4eDhUFn",
"slot": 462123500,
"transactionIndex": 206
}
],
"id": 1
}The RPC puts the memo's length in brackets before its text. Each memo is also on Solscan, and GET /api/log lists recent ones under anchors with their tx.
Check a memo against the log
Read the anchored size and root
From the memo:
log 398 cb97aebd….Fetch a consistency proof
From the anchored size to the newest checkpoint:
GET /api/log/consistency?from=398&to=<size>. If the sizes are equal, the roots must be equal.Verify it
With
verifyConsistencyfrom Proofs, the anchored root as the old root and the checkpoint's root as the new one. A proof that fails means the log you are shown is not the one that was anchored.
The state part works the same way: its root is the root of the commitment at that height (GET /api/log/state/<name>?height=394 returns it as commit).
Bitcoin timestamps
Once a day the sequencer timestamps the newest checkpoint and state commitment on Bitcoin through OpenTimestamps, using three public calendars. The timestamped digest is:
SHA-256( checkpoint note ‖ state statement )where checkpoint note is the full signed text served by /api/log/checkpoint at that time and state statement is the commitment's signed statement (left out when there is none). Each Bitcoin entry in anchors gives the digest, the size, logRoot, height, stateRoot and usdc it covers, and which calendars accepted it:
{
"chain": "bitcoin",
"at": 1793035086989,
"size": 354,
"logRoot": "370ab7aa09ee8a6418614941e15a5c292c28125342b10e4c6e85678fc4196e51",
"height": 352,
"stateRoot": "50f9504d4712a204119bad09de00d6d1d3f160d5dc611848b046d59bd36b4b35",
"usdc": "12285277511",
"digest": "eeb9fda28df49ff17926b81752e0ac71e2e0a8faa153f0320638c08630c95065",
"calendars": ["https://a.pool.opentimestamps.org", "https://b.pool.opentimestamps.org", "https://a.pool.eternitywall.com"]
}Download a receipt
https://mlx.app/api/log/ots/eeb9fda28df49ff17926b81752e0ac71e2e0a8faa153f0320638c08630c95065?cal=0A standard .ots file for one calendar's receipt of that digest.
| Parameter | Type | Notes |
|---|---|---|
digest | path | The anchor's digest, 64 hex characters. |
cal | integer | Which calendar: 0 a.pool.opentimestamps.org, 1 b.pool.opentimestamps.org, 2 a.pool.eternitywall.com. Default 0. |
Errors are plain text: 400 bad request (digest or cal malformed), 404 not found (no receipt from that calendar).
Verify it
A fresh receipt is pending; the calendar adds it to a Bitcoin transaction within a few hours. Then, with the OpenTimestamps client:
ots upgrade mlx-eeb9fda28df4-0.ots # fetch the Bitcoin attestation from the calendar
ots verify -d eeb9fda28df49ff17926b81752e0ac71e2e0a8faa153f0320638c08630c95065 mlx-eeb9fda28df4-0.otsots verify checks the attestation against Bitcoin block headers (the client reads them from a Bitcoin node; see its README). That proves the digest existed by that block. To tie the digest to a log root, hash the checkpoint note and statement yourself and compare: this needs the exact note that was anchored. Fetch it with GET /api/log/checkpoint?size=N, where N is the log size the anchor names.