Sans-I/O interpreter

Deterministic interpreter

The interpreter is a pure function over state. It takes verified facts, current replicated state, local node context, and completed call results from the secret kernel. It returns updated state, outgoing peer messages, local service requests, and a status.

sans-i/o step modelOne deterministic transition: facts and call results in, state and messages out.
inputs
valid ingressadmitted peer fact
execution contextreplicated state + local node context
call resultsCallResult from the kernel
interpreterstep(ingress, context, call_results)pure · deterministic · Sans-I/O · does no I/O of its own
DonePendingRemoteAbortFailedpublish-ready
outputs
outgoing messagesto peer nodes
updated contextinput to the next step
call requestsCallRequest to local services
local node calls · HSM API + system services
CallRequest →secret-dependent steps run behind the kernel — the interpreter only sees handles and results← CallResult
N-01

Inputs and outputs

Facts only enter the interpreter after they've been validated: transport checked, peer signatures verified, sender binding confirmed, replay safety established, session admitted. Local CallResult values from the secret kernel follow the same path — bound to call ids and merged with replicated state. The step function returns one of five statuses: Done, PendingRemote, Abort, Failed, or a publication-ready terminal state.

N-02

Replayable execution

Determinism is scoped to execution over admitted inputs. Approvals, policy decisions, and publication holds are admission-time events: each produces a recorded decision artifact, and execution is a deterministic function of those recorded facts. Variability lives at admission; replay operates over the decisions as recorded.

Because the interpreter is deterministic and depends only on facts and call results, a DVM transition replays from durable state. The enabler is content-addressing: every value in DVM state is indexed by a content-addressed id (Cid), so the replay inputs are fully determined by those ids, independent of mutable in-memory state. That keeps regression tests, inspection, recovery, and evidence export tractable.

The same semantic score also runs against different backend profiles. Swapping backends changes L0 microcode details but leaves the L1 operation contract and public evidence shape stable, which is why the API surface and audit records don't change across backend upgrades.

N-03

Layer contract

The three-layer separation is what gives the interpreter its determinism guarantee. It evaluates L1 operations against facts and call results, leaving L0 wire details and L2 product decisions outside its view. Share multiplication stays one L1 instruction whether the backend runs MRR21 setup, OT extension, DKLS23 gadget work, or a witness closure. Promoting L0 substeps to L1 opcodes would tie the score to one backend and break the replay guarantee, so the layer boundary holds them apart.

N-04

Two input kinds, no I/O of its own

The step function distinguishes two kinds of input. External API commands — a user's signing request — reach the interpreter only through the client API and the admission contour. Intra-cluster messages — the round traffic of the signing protocols — arrive over the transport bridge as already-admitted ingress representations. Only that second kind is handed to step() as a fact.

The interpreter performs no I/O itself. Outgoing messages are returned to the host, which drives the transport layer; every secret-dependent operation is expressed as a CallRequest to the local node and resolved later as a CallResult. Holding I/O and secret access outside the function keeps the transition pure, content-addressed, and replayable.