archon

Archon Solana mediator

The Solana mediator anchors Archon DID batches on Solana by publishing Archon-formatted memos. It supports canonical SOL:mainnet-beta and SOL:devnet registries.

The mediator has two responsibilities:

The memo payload intentionally does not validate Archon DID semantics. Gatekeeper remains the validation authority; Solana is used as a publication, ordering, and timestamping layer.

An Archon memo commits to the batch DID’s signed create operation. Import uses gatekeeper.getGenesis(did) and reads the ordered didDocumentData.batch.ops list. Retrieval checks identity/shape without requiring publisher authorization or accepted DID history; contained operations are still authorized normally. A later batch-asset update cannot change the operations or their opidx values for the existing anchor. Missing genesis content is retried rather than replaced with latest asset state.

Each import cycle also syncs finalized Solana block checkpoints into Gatekeeper for every produced block whose block height is at least ARCHON_SOL_START_BLOCK and divisible by 100. The mediator uses Solana slots as an internal scan cursor, but Gatekeeper block records and DID registration metadata use produced block heights so independent nodes can derive the same lower-bound timestamps.

Mediator metrics distinguish slot scan state from produced block heights:

Canonical memo format

The Solana registries use the Solana Memo program with an Archon-specific payload prefix:

ARCHON_BATCH_V1:{"batchHash":"0x...","batchDid":"did:cid:...","opCount":1}

Every node on a canonical Solana registry should scan the same registry address and payload format. The default registry address is a deterministic ed25519 keypair derived from a SHA-256 of the literal string archon-solana-registry-signer-v1, the chain (e.g. SOL:mainnet-beta or SOL:devnet), and the Memo program ID; the wallet uses this keypair as a co-signer on every anchor so the address is genuinely controlled by all nodes. Wallet anchors include that address as a signer on the Memo instruction so discovery can query a narrow address instead of the global Memo program. A future custom Solana program can replace this format under a distinct registry name or explicit non-canonical configuration.

Environment variables

variable default description
ARCHON_NODE_ID none Keymaster agent name used as batch controller
ARCHON_GATEKEEPER_URL http://localhost:4224 Gatekeeper service URL
ARCHON_KEYMASTER_URL none Keymaster service URL
ARCHON_WALLET_URL none Solana wallet service URL
ARCHON_ADMIN_API_KEY none Admin API key for service-to-service calls
ARCHON_SOL_CHAIN network derived Gatekeeper registry name, e.g. SOL:devnet
ARCHON_SOL_NETWORK mainnet-beta mainnet-beta, devnet, testnet, or local
ARCHON_SOL_RPC_URL network derived Solana JSON-RPC endpoint
ARCHON_SOL_COMMITMENT confirmed Commitment for transaction submission/pending tracking; imports always use finalized
ARCHON_SOL_MEMO_PROGRAM_ID Memo program Solana Memo program ID to scan and publish to
ARCHON_SOL_START_BLOCK 0 First produced block height to checkpoint and import/register
ARCHON_SOL_SIGNATURE_PAGE_LIMIT 100 Signatures per getSignaturesForAddress page
ARCHON_SOL_SIGNATURE_PAGE_MAX 20 Maximum signature pages per import loop
ARCHON_SOL_PENDING_TX_TIMEOUT_SLOTS 150 Slots to wait before re-anchoring a stale pending transaction
ARCHON_SOL_MIN_BALANCE_LAMPORTS 10000000 Minimum wallet balance required before anchoring
ARCHON_SOL_IMPORT_INTERVAL 0 Minutes between import cycles; 0 disables importing
ARCHON_SOL_EXPORT_INTERVAL 0 Minutes between export cycles; 0 makes the mediator read-only
ARCHON_SOL_REIMPORT true Reprocess discovered batches on startup
ARCHON_SOL_DB json Database adapter: json, sqlite, mongodb, or redis
ARCHON_SOL_DB_NAME chain derived Persister file/key name, derived from the registry chain by default (transform: chain.replace(/:/g, '-'))
ARCHON_SOL_METRICS_PORT 4249 Metrics server port

Batch completion and pending events

Gatekeeper’s processEvents().pending is a global queue count. When nonzero, pendingBatches identifies the batch DIDs still represented in that queue. After importing every CID, the mediator completes a batch only after a non-busy processing result that has no pending events for that batch. Unrelated pending events do not trigger reimports. This records processing completion, not final authorization; retained history can still be replayed when missing evidence arrives.

Batch import logs report batchImport and batchComplete for this batch; gatekeeperQueueAfterImport and gatekeeperProcessing describe the node-global inbound queue. Persisted imported and processed keep the raw API responses.

Unavailable content, incomplete CID results, processing failures, and batches with their own pending events remain retryable. Older Gatekeepers that omit pendingBatches retain the conservative global-pending behavior. Persisted “No progress” errors recover through the normal retry pass without database edits.

Import finality

Discovery tips, signature listing, parsed transactions, and block retrieval all use finalized, independently of ARCHON_SOL_COMMITMENT. Gatekeeper therefore receives finalized Solana anchors; confirmed-only forks are not imported. This relies on Solana finality and does not provide recovery from a finalized-chain rollback. The setting still controls outbound transaction/pending tracking. Previously imported confirmed-only evidence is not automatically audited by this change; it prevents new discovery from using that weaker commitment.