Main
/
List
/
Categories
/
Tags
Four steps: a prompt program stored on chain, evaluators from many labs, a proof of inference, and a signed ruling the calling program verifies

Bringing Inference Programs To Solana

Three draft SIMDs to bring Actually Smart Contracts to Solana: prompts stored on chain, run by models off chain, proven, signed and open to challenge.

66 min read
November 5, 2026

Three draft SIMDs. All three are drafts, written to open a discussion, not yet submitted.

  1. Inference Programs: natural-language programs on chain, their internal context, and how other programs call them, inject external context, shape the jury and pay. (Markdown)
  2. Inference Evaluators and Attestations: who runs the models, what they commit to, the signed vote each one casts, and proofs of inference. (Markdown)
  3. Inference Rulings, Disputes and Challenges: the signed ruling programs act on, and how rulings are disputed, challenged with new evidence and overturned. (Markdown)

This started as one draft. It grew large enough that it reads better as three proposals that depend on each other, so each can be reviewed on its own.


Slide: Motivation. Trustless systems still run on human judgment: a DAO constitution with no one to enforce it, an insurance policy whose claims are judged off chain, an exchange hot wallet guarded only by code.

Blockchains have made real progress toward trustless, decentralized systems that run without anyone in charge. But they still lean on people for judgment: discussion, opinion, motives and alignment, all happening off chain. That reliance has been a steady source of inefficiency, and of risk.

A DAO can pass a constitution, but it has no full-time lawyers to enforce it. An insurer can write a policy that a smart contract is meant to pay out on, but deciding whether a claim qualifies still happens off chain, by people. An exchange may want to wrap its hot wallets in procedures that protect user funds, and find it can only enforce what code can express. Code is law, and code can’t say everything.

That’s why we think it’s time to talk seriously about how AI and blockchains can converge to add the missing piece: judgment, and policy checks built into the contract itself. A program should be able to get a second opinion, ask an expert panel, or go to a judiciary for a ruling before it moves funds. Done right, that means better security and more control over how funds are managed.

To that end, we’re introducing Actually Smart Contracts as a SIMD for Solana itself. Yesterday we introduced the idea: smart contracts you can write in English, enforced by a jury of AI models. Today we’re publishing three draft Solana Improvement Documents that would make it a shared standard, so every program, wallet and explorer can use it the same way.

The idea in one paragraph

Store a prompt on chain the way you’d store a program, along with the context that should shape the decision: policies, rules, a constitution, even a link to a DAO discussion. Let any Solana program call it. AI models run it off chain, and each one signs the result on chain: we ran this program, at this version, on this input, and this is the answer. A proof of inference shows which model actually did the thinking. The calling program checks the signatures before it acts.

Animation: a Solana program requests a ruling; AI models off chain read the prompt and context stored on chain, vote and attach proofs; the signed ruling is recorded on chain; the program verifies it and acts.

That changes what a smart contract can be. Today a program can only enforce what code can express: balances, signatures, dates. With an inference program, it can enforce a sentence like “the treasury shall not fund political campaigns.”

Why proof of inference is the key

Slide: each side does what it is best at. Solana keeps the record and triggers programs, models do the thinking off chain, and the proof joins them.

Proof of inference lets each side do what it’s best at.

Solana does what blockchains do best. It keeps a permanent, public record of decisions, certifications and proof statements, and of every payment. It stores the programs and the context the models should use, and it lets other programs trigger them.

Models do the deep thinking, off chain. Reading a constitution, weighing evidence and deciding whether an action breaks a rule takes large models on serious hardware. That work doesn’t belong on chain, and it doesn’t need to be there.

The proof joins them. It shows which model gave the answer, so the chain can trust a decision it didn’t compute. Without it, you’re trusting whoever ran the model. With it, you’re checking.

Together, that opens up a wide range of uses: DAO arbitration, ethics checks for AI models and agents, policy checks, certifications, and more.

Why now

Slide: two missing pieces, knowing which model ran and a common format.

Two pieces have been missing.

The first is a way to know which model ran. A signature proves which key signed, not which model did the work. Anthropic’s research on provable inference shows that a provider can prove a committed set of model weights produced a specific answer, without revealing the weights. It’s a research prototype today: proofs run to tens of megabytes and take seconds to verify, for one open model. That’s too large to check inside a Solana transaction, so the drafts verify proofs off chain and leaves room to bring verification on chain later.

The second is a common format. Without one, every team invents its own requests, signatures and results, and nothing can read them across applications. That’s what a SIMD is for.

What it would make possible

Slide: rules that code alone cannot enforce, from constitutions to agent policies, with Verafy Judiciary as an example.
  • Constitutions that hold. A DAO checks a passed proposal against its inscribed constitution before it executes.
  • Treasury guardrails. A withdrawal over a threshold waits for a ruling against a written policy.
  • On-chain certifications. A published standard, like “a consumer device shall never record without a visible indicator,” becomes a program. Models review a specific commit against it, and the ruling is a public certificate.
  • Judgment clauses. Grants and escrow that pay when what was promised actually happened.
  • Agent policies. Programs acting for AI agents check risky actions against the agent’s written limits.

For an example of what we have in mind, see Verafy Judiciary. You write your community’s rules once, and a jury of AI models from different companies applies them to a dispute and cites the clause behind each ruling. These SIMDs are how rulings like that could be recorded on chain, proven, and acted on by any Solana program.

What’s in the drafts

Slide: six pieces across three SIMDs: instructions, internal context and calls in SIMD 1; evaluators and attestations in SIMD 2; rulings in SIMD 3.

Across the three drafts there are six pieces. Inference Programs covers the first three, Evaluators and Attestations the next two, and Rulings, Disputes and Challenges the last.

  1. Instructions. What the inference program is for and the outcomes it may return, stored on chain in whatever form is smallest or most private.
  2. Internal context. The program’s own materials, which apply to every call: a DAO constitution or bill of rights, run rules, an insurance policy, certification standards. They can be stored inline, pulled from a web page, or pulled from a trusted GitHub repository pinned at a commit. It loads into the model’s context window with the prompt, so one call can run a policy check, a legal check, a tax check, an insurance check or a DAO rules check.
  3. Calls. Each call injects a request prompt (the question), external context (the evidence: a link, a paragraph, documents to check), jury shaping (which labs and models, how many, what level of proof) and payment. The caller gets a cost estimate first, escrows a budget that pays the model providers, is refunded what’s left, and gets a callback to add funds if it runs short. External context never overrides internal context.
  4. Evaluators. Model operators register a signing key and a commitment to exactly what they run: hashes of the weights, the tokenizer and the decoding settings.
  5. Attestations. One exact message format for the signature, bound to one request, its instructions, its internal and external context, and its input. Votes are committed before they’re revealed, and checked with Solana’s existing Ed25519 verification.
  6. Rulings. The contract writes back a signed decision, like a court opinion: the outcome, a short summary, the full reasoning, the sources it relied on (each checked against the internal and external context it was given), how strongly the models agreed, every model’s wallet signature, and a sign-off where one model writes the opinion and the others co-sign it. Dissents stay on the record. Quorum, a safe default, disputes and three assurance levels come with it.
Diagram: anatomy of an Actually Smart Contract. The caller injects a request prompt, external context, jury shaping and payment; the inference program holds its instructions and pulls its internal context; evaluators off chain rule and return a signed ruling. Slide: calling an Actually Smart Contract. Inject a request prompt and external context, shape the jury, and pay from escrow with a quote, refunds and a top-up callback. Block diagram: what goes into a request. The RulingRequest account holds pinned rules, the question, external context, jury shaping, payment, and callbacks and deadlines, fed by the caller, the inference program and content accounts, and read by evaluators. Diagram: what the contract writes back, a signed ruling with decision, certainty, pinned hashes, summary, reasoning, sources used, signatures, sign-off and dissents, returned to the calling program. Block diagram: what a ruling records on chain, field group by field group with bytes: header, pinned hashes, decision, certainty, opinion, sources, vote signatures, sign-offs and dissents, with long material off chain by hash and a compact answer returned by ReadRuling.

Small, private and changeable

Slide: small, private and changeable. A compact form, encryption, and updates that never rewrite past rulings.

Models don’t need tidy English. A prompt can be written in any language and compiled into a terse form a model still reads directly. One of our 178-byte withdrawal rules compiles to 68 bytes:

R5 HOLD if acct_sec_change<=48h(pw|email|2fa) AND dest∉prior_dests

On top of that, content can be compressed, and encrypted so that only the chosen evaluators can read it. Everyone else sees a hash. Evaluators decompress and decrypt before the model sees anything.

Context can also be a link: a DAO forum thread, a governance proposal, a web page. Live pages change, so a link is captured once into a snapshot with its hash, and every model rules on that same snapshot. To rule on a newer version, take a new snapshot.

Storage is cheap. Our five draft standards, about 3,400 words together, compress to about 5 KB, which costs roughly 0.04 SOL in rent at today’s rates. A single account holds up to 10 MiB. The real limit is the model’s context window, so every program declares a context budget and evaluators declare what they can take.

And both the prompt and its context can change. Whoever creates the program can update them at any time, stage changes behind a public delay, or freeze them for good. Every ruling pins the exact hashes it used, so a change never rewrites a past decision.

Rulings can be challenged and overturned

A ruling isn't the last word, and it shouldn't be. Evidence turns out to be forged, a source is corrected, or the reasoning looks wrong once more is known. Courts deal with this by letting a later court overturn an earlier decision, sometimes generations later, while the original stays in the record. Inference programs work the same way.

There are two kinds of review. A dispute is quick: within a short window, a fresh ruling is re-judged on the same evidence by different model families, before anyone relies on it. A challenge can come at any time, with no deadline. The challenger names the grounds (new evidence, false evidence, misapplied rules, or rules that have since changed), posts a bond and pays for the review. The challenge jury gets the original ruling and its full reasoning, the original evidence, and the new material, clearly labeled as new. It has to compare itself to the original, source by source, and say which new source changed the answer.

Slide: any ruling can be challenged, none is erased. Ruling R1, a dispute days later, new evidence years later, then a challenge ruling R2 that compares itself to R1 and overturns it. Grounds, results and guards listed.

The result is affirmed, overturned, or superseded when the rules themselves changed. Nothing is erased: the original stays on chain, marked overturned, with a link to the ruling that overturned it, so the whole history can be read back. Past actions stay settled. What changes is the record and what programs do next. An insurer can pay a claim whose denial was overturned, and no program may act on an overturned ruling. To stop a losing side from relitigating until it draws a friendlier jury, every challenge must bring something no earlier review considered, the bond is returned only if the challenge wins, and each review uses fresh model families. Past rulings can also be cited as precedent in a program's context, always with their review status attached.

Faster and cheaper: System 1 models

A ruling from a jury of language models takes 20 to 60 seconds in our recorded runs. That's fine for a DAO proposal and too slow for an agent's loop or a busy withdrawal queue. A new kind of model may help. TypeSafe's Jev is what they call a System One model: instead of writing text, it returns a typed answer (a choice, a score, or a yes or no) with a calibrated probability, in 70 to 500 milliseconds and for about $0.0004 a decision, by the vendor's own figures.

The names come from psychology: System 1 is the fast gut check, System 2 is slow, careful reasoning. In an inference program, System 1 screens and System 2 rules. Each rule in the program's internal context becomes one yes or no question, checked in parallel. A clear, low-stakes case gets a fast result or the safe default. An unclear or costly one escalates to the full jury, and the screen's probability can decide how big that jury should be.

Slide: System 1 screens, System 2 rules. A request goes to a System 1 screen that returns a typed answer and probability per rule; clear, low-stakes cases get a fast result or the safe default, unclear or high-stakes ones go to the full jury. Pluses and minuses listed.

The pluses are real. It's sub-second, so it fits where a jury can't. Its typed answers map straight onto the outcomes a program lists. Its probabilities are trained to be calibrated, which beats a language model reporting how confident it feels. The minuses matter as much. It writes no reasoning, so it can't produce the opinion, summary and sources a ruling needs. It's one hosted, closed model, so it adds no diversity of labs and can't carry a proof of inference. On TypeSafe's own benchmark it scored 67.8% against 73 to 74% for frontier models, and calibrated isn't the same as correct. So it's the fast lane, not the court: the attestations draft adds an informative section on using System 1 models as a screen, as an evaluator that votes but doesn't write the opinion, and to size the jury.

What it doesn’t do

Slide: honest limits. No validator changes, no on-chain proof checks yet, and models are not infallible.

It doesn’t change the validator. Everything in the drafts can be built as a Solana program today. It doesn’t verify proofs of inference on chain, because they’re still too big. And it doesn’t make models infallible: in our tests, a forged correction in the evidence fooled all ten models we tried. The drafts say so, and ask calling programs to keep hard limits in their own code.

Next step

Slide: next step, opening the idea to Solana in the SIMD Ideas discussion.

Solana’s SIMD process asks that ideas be discussed before a proposal is submitted. We’re opening a discussion in the SIMD repository’s Ideas section to find out whether this is viable, what’s wrong with it, and who wants to build it with us. All three drafts are below.

See Actually Smart Contracts run.


SIMD 1 (draft): Inference Programs

simd: 'XXXX'
title: Inference Programs
authors:
  - Rex St. John (Verafy)
category: Standard
type: Interface
status: Idea
created: 2026-11-05
feature: (fill in with feature key and github tracking issues once accepted)

Summary

These SIMDs are part of a broader proposal to bring Inference Programs to Solana natively: Bringing Inference Programs To Solana.

This proposal defines inference programs: programs written in natural language, stored on chain, called by other Solana programs, and executed off chain by AI models. It standardizes how a program's prompt and context are stored (inline, from a web page or a git repository at a commit, compact, compressed or encrypted), how they change over time, and how a caller requests a ruling: with a request prompt, external context, a jury specification, and an escrowed budget that pays the model operators and refunds the rest.

This is one of three companion proposals that bring inference programs to Solana:

  1. Inference Programs: natural-language programs on chain, their context, and how other programs call and pay for them.
  2. Inference Evaluators and Attestations: who runs the models, what they commit to, and the signed, optionally provable, vote each one casts.
  3. Inference Rulings, Disputes and Challenges: how votes become a signed ruling that programs act on, and how rulings are disputed, challenged and overturned.

The motivation, use cases and diagrams for all three are in the overview post.

Motivation

A smart contract can enforce only what code can express: balances, signatures, timestamps and arithmetic. Many rules that matter most to on-chain organizations are judgments: "the treasury shall not fund political campaigns", "what a proposal does must match what its text says", "hold any withdrawal that looks like an account takeover". Today they live in forum posts and constitutions that nothing on chain can check, and judgment happens off chain, by a multisig or a vote.

Large language models can read and apply rules like these. To use them from a smart contract, the rules need a public, versioned home on chain, every ruling must name the exact text it applied, and calling programs need one way to ask, pay and read back. This proposal provides the first two and the request side of the third.

Dependencies

This proposal depends on the following proposals, submitted together:

  • SIMD-XXXX: Inference Evaluators and Attestations

    Defines the evaluators that serve a request, and the JurySpec fields that refer to them.

  • SIMD-XXXX: Inference Rulings, Disputes and Challenges

    Defines the Ruling that answers a request, and uses the request kind and reviews fields.

New Terminology

  • Inference program: An on-chain account that names a prompt, a context set, an output schema and evaluation requirements.

  • Prompt: The instructions the model follows, with the list of allowed outcomes.

  • Context set: An ordered list of context documents (policies, rules, a constitution, standards, contract terms, or linked pages such as a DAO discussion) that evaluators load into the model's context alongside the prompt.

  • Internal context: The inference program's own materials, which apply to every request: a DAO constitution or bill of rights, run rules, an insurance policy, standards. Stored inline, or pulled from a web page or a trusted GitHub repository pinned at a commit.

  • External context: Context a caller injects into one request: the evidence and case being decided, as links, text or documents. It never overrides internal context.

  • Request prompt: The caller's question for one request, such as "Does proposal 42 comply?". It works within the program's instructions and cannot add outcomes.

  • Jury specification: The part of a request that says who may rule: how many evaluators, the quorum, the required assurance level, and which model families or specific models are allowed.

  • Budget: Lamports a requester escrows to pay evaluators and verifiers. Unspent budget is refunded.

  • Linked content: A context document or evidence item given as a URL. It is fetched once into a snapshot, and every evaluator reads the same snapshot.

  • Content account: An account that holds one prompt or one context document, in any supported encoding, inline or by external reference.

  • Encoding: How stored bytes become model input: plain text, a compact compiled form, compressed, encrypted, or a combination.

  • Context budget: The number of tokens an evaluator must be able to accept for the prompt, context and input together.

  • Revision: A counter that increases every time a prompt or context set changes.

  • Mutability mode: Whether a creator can change content immediately (mutable), only after a public delay (timelocked), or never (frozen).

  • Ruling request: An account recording a request to run one inference program on one input, with the pinned prompt and context hashes, quorum and deadlines.

Detailed Design

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

All integers are little-endian. All hashes are SHA-256 unless stated otherwise. Account layouts begin with an 8-byte discriminator equal to the first 8 bytes of sha256("inference-programs:" || account_name).

Accounts

InferenceProgram
discriminator        [u8; 8]
authority            Option<Pubkey>  // None once frozen
mutability           u8         // 0 mutable, 1 timelocked, 2 frozen
update_timelock      u64        // slots, used when mutability = 1
revision             u32        // +1 on every prompt or context change
prompt               Pubkey     // Content account holding the prompt
context_set           Option<Pubkey>  // ContextSet account
pending_prompt       Option<Pubkey>  // staged change, timelocked mode
pending_context_set   Option<Pubkey>  // staged change, timelocked mode
pending_after        u64        // slot after which staged changes apply
context_budget       u32        // tokens evaluators must accept
ext_context_mode     u8         // 0 not accepted, 1 optional, 2 required
ext_context_kinds    u16        // bit per ContextEntry kind a caller may add
ext_context_budget   u32        // tokens of external context allowed
min_evaluators       u8         // floor on evaluators per request
min_quorum           u8         // floor on agreeing attestations
min_assurance        u8         // 0, 1 or 2
distinct_families    bool       // require distinct model families
default_outcome      u8         // outcome on expiry or no quorum
evaluator_set        Option<Pubkey>  // optional EvaluatorSet account
name                 [u8; 64]   // UTF-8, zero padded
Content

Holds one prompt or one context document.

discriminator        [u8; 8]
authority            Option<Pubkey>
revision             u32
content_hash         [u8; 32]   // sha256 of the stored bytes
source_hash          [u8; 32]   // sha256 of the plain-text source, or zero
encoding             u8         // bit flags, see "Encodings"
stored_len           u32        // bytes held here or externally
decoded_len          u32        // bytes after decryption and decompression
token_estimate       u32        // creator's estimate of model tokens
storage_kind         u8         // 0 inline, 1 external, 2 link,
                                // 3 git repository
external_ref         [u8; 96]   // e.g. an inscription's transaction
                                // signature, zero padded
link                 [u8; 256]  // URL when storage_kind is 2 or 3
git_commit           [u8; 20]   // pinned commit when storage_kind = 3
git_path             [u8; 128]  // file or folder in the repository
snapshot_slot        u64        // when the linked page was captured
key_envelope         Option<Pubkey>  // KeyEnvelope account, if encrypted
outcome_count        u8         // prompts only
outcomes_hash        [u8; 32]   // prompts only: sha256 of outcome list
writing              bool       // true while chunks are being written
updated_slot         u64
content              [u8]       // inline bytes when storage_kind = 0

Content larger than one transaction is written in chunks with WriteContentChunk while writing is true. SealContent MUST check that the sha256 of the bytes equals content_hash and sets writing to false. Evaluators MUST NOT use content while writing is true.

With storage_kind = 1, the bytes live elsewhere (for example, an inscription stored by another program, or a content-addressed store) and only the hash is held here. Evaluators MUST fetch the bytes, check that their sha256 equals content_hash, and refuse to attest otherwise.

Linked content. With storage_kind = 2, the content is a page on the web, such as a DAO forum thread, a governance proposal, a news article or a terms-of-service page. Live pages change, and evaluators fetching them at different moments would rule on different text. So a link is always ruled on through a snapshot:

  1. SnapshotLink records the sha256 of the captured page in content_hash, a reference to the stored copy in external_ref, and snapshot_slot. Any signer may capture a link that has no snapshot yet. A program MAY limit capture to its authority or to listed evaluators.
  2. Requests pin the snapshot's content_hash, like any other content. Evaluators MUST read the snapshot, not the live page, and MUST refuse to attest if it does not match the hash.
  3. To rule on a newer version of the page, take a new snapshot. That changes the context hash, so it is a new revision.

Git repositories. With storage_kind = 3, the content is a file or folder in a git repository the creator trusts to publish its rules, pinned at git_commit. content_hash is the sha256 of the files at that commit, in sorted path order. Moving to a newer commit is an update like any other, so it follows the program's mutability mode.

Snapshots SHOULD store the page as text with its URL, title and capture time, and SHOULD strip scripts and markup. Requests can also carry links as evidence: the requester snapshots each linked page, and evidence_hash covers the snapshot hashes.

ContextSet
discriminator        [u8; 8]
authority            Option<Pubkey>
revision             u32
context_hash         [u8; 32]   // sha256 over the ordered list of
                                // (kind, label, content_hash) entries
count                u8
entries              [ContextEntry; count]

ContextEntry:
  content            Pubkey     // Content account
  content_hash       [u8; 32]   // must equal that account's content_hash
  kind               u8         // 0 constitution, 1 standard, 2 regulation,
                                // 3 contract terms, 4 internal policy,
                                // 5 rules, 6 discussion, 7 web page,
                                // 8 other shaping context,
                                // 9 prior ruling (see Rulings)
  label              [u8; 32]   // e.g. "EDO v1.0", zero padded

A context set lets one inference program apply several rule sets at once. For example, a certification program can hold its standards (EDO v1.0 and EAO v1.0) as two entries, and a treasury program can hold the DAO constitution and the treasury policy. Context sets MAY be shared by many inference programs.

Evaluators MUST place the context documents in the model's context in entry order, before the prompt and the input, each preceded by its kind and label. The prompt SHOULD instruct the model to cite the context entry and section behind each finding.

KeyEnvelope (encrypted content only)
discriminator        [u8; 8]
content              Pubkey
scheme               u8         // 0 = X25519 + HKDF-SHA256 + ChaCha20-Poly1305
count                u8
wraps                [KeyWrap; count]

KeyWrap:
  evaluator          Pubkey     // Evaluator account
  ephemeral_pub      [u8; 32]
  wrapped_key        [u8; 48]   // content key encrypted to the evaluator
RulingRequest

A PDA at ["request", inference_program, requester, nonce_le_u64].

discriminator        [u8; 8]
inference_program    Pubkey
revision             u32        // pinned at creation
prompt_hash          [u8; 32]   // pinned prompt content_hash
context_hash         [u8; 32]   // pinned context_hash, or zero
requester            Pubkey
input_hash           [u8; 32]   // sha256 of the canonical input
input_ref            [u8; 96]   // where evaluators fetch the input
evidence_hash        [u8; 32]   // sha256 over sorted evidence hashes,
                                // or zero
ext_context_hash     [u8; 32]   // sha256 over the external context, or zero
ext_context_count    u8
ext_context          [ContextEntry; 8]  // caller-supplied documents
request_prompt_len   u16
request_prompt       [u8; 1024] // the caller's question, UTF-8
jury                 JurySpec
max_input_tokens     u32        // cap used for pricing and context checks
max_output_tokens    u32
budget               u64        // lamports escrowed in this account
quoted               u64        // estimate from QuoteRuling at request time
spent                u64        // paid out so far
refund_to            Pubkey     // receives what is left
callback_program     Option<Pubkey>  // notified of the events below
callback_events      u8         // bits: final, needs funds, expired,
                                // disputed
topup_deadline       u64        // slot by which a shortfall must be covered
commit_deadline      u64        // slot
reveal_deadline      u64        // slot
opinion_window       u64        // slots for the rapporteur to post
signoff_deadline     u64        // slot by which sign-offs must land
dispute_window       u64        // slots after finalization
kind                 u8         // 0 ruling, 1 dispute, 2 challenge
reviews              Option<Pubkey>  // the Ruling under review, if any
status               u8         // 0 open, 1 revealing, 2 final,
                                // 3 disputed, 4 expired, 5 closed,
                                // 6 needs funds

JurySpec:
  evaluators         u8         // number of attestations sought (n)
  quorum             u8         // agreeing attestations required (k)
  assurance          u8         // 0 signatures, 1 diverse, 2 proven
  distinct_families  bool
  family_count       u8
  allowed_families   [[u8; 32]; 8]  // empty = any family
  model_count        u8
  allowed_models     [Pubkey; 8]    // ModelCommitment accounts,
                                    // empty = any model
  max_fee_each       u64        // most any one evaluator may be paid
  verifier_fee       u64        // per proof verification, for L2

RequestRuling MUST set the jury's evaluators, quorum and assurance to at least the inference program's minimums, MUST NOT allow a model or family outside the program's evaluator set when it has one (a request can narrow the jury, never widen it), and MUST copy revision, prompt_hash and context_hash from the program as it stands at that slot. A request MAY instead name an earlier revision's hashes, if that content is still retrievable.

Encodings

Models do not need prompts in tidy English. A prompt or context document can be stored in whatever form is smallest or most private, as long as evaluators can turn it into model input. encoding is a set of bit flags, applied in this order when writing and reversed when reading:

  • Bit 0, compact. A compiled, terse form of the source that a model reads directly: abbreviations, symbols and structured shorthand instead of full sentences. The source can be written in any human language. For example, this 178-byte rule:

    Hold the withdrawal if it looks like an account takeover: a password, email or 2FA change in the last 48 hours, followed by a withdrawal to an address the account has never used.

    compiles to 68 bytes:

    R5 HOLD if acct_sec_change<=48h(pw|email|2fa) AND dest∉prior_dests
    

    Compact content MUST carry a non-zero source_hash, so anyone holding the plain source can check which text it was compiled from. Creators SHOULD test that the compact form produces the same rulings as the source on a set of sample inputs, because compilation can change meaning.

  • Bit 1, compressed. zstd. Evaluators MUST decompress before building model input. Models do not read compressed bytes directly.

  • Bit 2, encrypted. ChaCha20-Poly1305 under a random content key, wrapped to each listed evaluator's X25519 key in a KeyEnvelope. Only those evaluators can read the content. Everyone else sees the hash, the length and the token estimate. Evaluators MUST decrypt before building model input.

content_hash always covers the stored bytes, so the chain can check that nothing changed. source_hash covers the human-readable source, so a creator can later publish the source and prove it is what the models ran.

Storage size and cost (informative)

Content accounts can hold up to 10 MiB. Larger content is written in chunks. At current parameters a rent-exempt account costs 6,960 lamports per byte plus a 128-byte header, refunded when it is closed. Five certification standards together (22,712 bytes of text) compress to 5,246 bytes, about 0.0377 SOL of rent; measurements for other texts are in the overview post. In practice the limit is the evaluator's context, not storage: the prompt, all context and the input must fit within context_budget. Creators SHOULD set token_estimate on every content account.

Mutability

Creators can change both the prompt and the context set. How fast depends on mutability:

  • Mutable (0). SetPrompt, SetContextSet and UpdateContent take effect in the slot they land, and revision increases.
  • Timelocked (1). Changes are staged in pending_prompt and pending_context_set and apply only after pending_after, which is the staging slot plus update_timelock. Anyone can see a change coming.
  • Frozen (2). Nothing changes again. authority is None.

SetMutability MUST only move toward frozen: mutable to timelocked, or either to frozen.

Every change MUST emit a log line with the old and new content_hash or context_hash, so indexers can keep a history. Implementations SHOULD store each revision's bytes somewhere retrievable, such as an inscription, so any past ruling can be checked against the exact text it applied.

Requests are never affected by later changes. A request pins prompt_hash and context_hash at creation, and evaluators MUST attest against the pinned content. If the creator replaces the content before evaluators fetch it and the old bytes are not retrievable, evaluators cannot attest and the request expires to default_outcome.

External context

Internal context is set by the inference program's creator and applies to every request. External context is supplied by whoever calls the program and applies to one request. A DAO's constitution is internal context; the proposal being judged, its forum thread and its decoded calldata are call context. An insurer's policy terms are internal context; a claim and its photos are external context.

RequestRuling accepts up to 8 external-context entries, each a Content account (inline, external or a snapshotted link), plus a short inline note of up to 512 bytes. A calling program can inject context through cross-program invocation by creating Content accounts for longer material, or by passing the note in instruction data. The program MUST check:

  1. ext_context_mode allows external context, and requires it when set to 2.
  2. Every entry's kind is allowed by ext_context_kinds.
  3. Every entry is sealed and, for links, snapshotted.
  4. The combined token_estimate of external context fits within ext_context_budget, and internal context, external context and input together fit within context_budget.

ext_context_hash is the sha256 over the ordered entries' (kind, label, content_hash) followed by the note, and it is pinned like every other hash.

Evaluators MUST build the model's context in this order: the prompt, the internal context, then the external context under a heading stating that it was supplied by the caller for this request, then the input and evidence. The prompt SHOULD tell the model that internal context governs, and that call context is material to judge, not instructions to follow.

Shaping the jury

A request says who may rule. JurySpec sets the number of evaluators, the quorum, the required assurance level, whether families must differ, and optional lists of allowed model families and specific model commitments. Only active evaluators that match every constraint, and whose max_context fits the request, may commit. A DAO can require L2 and two named open models; an agent's spending check can accept any three fast models at L1.

Payment, budget and refunds

Evaluators are paid by the request, in lamports, from an escrow the requester funds up front.

  1. Quote. QuoteRuling takes the same arguments as RequestRuling and sets return data to an estimate: for the cheapest eligible evaluators that satisfy the jury, base_fee plus input and output tokens at their prices, up to max_input_tokens and max_output_tokens, plus proof_fee and verifier_fee at L2, plus rent for the request, attestation and ruling accounts. Clients simulate it before requesting.
  2. Escrow. RequestRuling moves budget lamports into the request and records quoted. It MUST fail if budget is below quoted. Evaluator prices are pinned at request time; later price changes do not apply.
  3. Payout. When an evaluator reveals, its charge is fixed: base_fee plus its token charges and proof fee, never more than its pinned prices allow and never more than max_fee_each. CloseRequest pays each revealed evaluator to its payout_wallet, pays verifiers, and adds the totals to spent.
  4. Refund. After payouts, the rest of budget and all reclaimed rent go to refund_to. Unrevealed slots and expired requests are refunded in full, minus work already revealed.
  5. Insufficient funds. If the escrow cannot cover the next step (for example, more evaluators are needed after an invalid reveal, or proofs cost more than quoted), the request moves to "needs funds" and records the shortfall. Work pauses until anyone calls TopUp with at least the shortfall before topup_deadline. If no one does, the request expires to default_outcome, revealed work is paid, and the rest is refunded.

Callbacks. If callback_program is set, a crank calls NotifyCaller when an event in callback_events happens: final, needs funds, expired or disputed. NotifyCaller invokes the callback program with the request, the event and, for "needs funds", the shortfall. Callbacks only notify. They move no funds, and a callback program MUST re-check the ruling with ReadRuling before acting on it. Programs that do not use callbacks can poll the request.

This proposal does not define staking or slashing. Implementations MAY add bonds, and SHOULD record equivocation (an evaluator revealing two different outcomes for one request) so that clients can exclude that evaluator.

Instructions

  • CreateContent (signer: authority): Creates a Content account with its hash, length, encoding and token estimate.

  • WriteContentChunk (signer: authority): Writes inline bytes at an offset while writing is true.

  • SealContent (signer: authority): Checks the hash and marks the content ready.

  • UpdateContent (signer: authority): Replaces a Content account's bytes and hash, subject to the owning program's mutability.

  • SnapshotLink (signer: any, unless the program restricts it): Records a linked page's snapshot hash, reference and slot.

  • SetKeyEnvelope (signer: authority): Attaches or replaces the key wraps for encrypted content.

  • CreateContextSet and SetContext (signer: authority): Create a context set or replace its entries.

  • CreateInferenceProgram (signer: authority): Creates the program with its prompt, context set, budget and minimums.

  • SetPrompt and SetContextSet (signer: authority): Point the program at new content, immediately or staged, by mutability mode.

  • ApplyPending (signer: anyone): Applies staged changes after pending_after.

  • SetMutability (signer: authority): Moves toward frozen.

  • QuoteRuling (signer: none): Estimates the cost of a request and returns it as return data.

  • RequestRuling (signer: requester): Creates a RulingRequest with its call context and jury, and escrows the budget.

  • TopUp (signer: anyone): Adds lamports to a request's escrow, and resumes it when the shortfall is covered.

  • NotifyCaller (signer: anyone): Sends a pending event to the request's callback program.

  • CloseRequest (signer: anyone, after the ruling is final or expired): Pays evaluators and verifiers, refunds the rest to refund_to, reclaims rent.

Commit, then reveal. Each evaluator first submits only sha256(message || salt) before commit_deadline. After that slot, the evaluator (or anyone holding the message, salt and signature) calls RevealAttestation. The program MUST check that:

  1. The transaction contains an Ed25519 precompile instruction verifying signing_key's signature over the message. The program reads it with instruction introspection.
  2. The message fields match the request and the evaluator's model commitment.
  3. sha256(message || salt) equals the stored commitment.

No evaluator can see another's answer before committing to its own.

Finalization. After reveal_deadline, FinalizeRuling counts revealed attestations by outcome. If at least quorum agree on one outcome, and that quorum meets the program's family and assurance requirements, the Ruling records that outcome. Otherwise the Ruling records default_outcome with certainty.agreeing below quorum. Calling programs MUST treat that as "no ruling".

Edge Cases

  • Content changes during a request. Requests pin hashes at creation. Evaluators attest only against pinned content. If it is no longer retrievable, the request expires.

  • Frozen programs. SetPrompt, SetContextSet, UpdateContent and SetContext MUST fail once the relevant authority is None.

  • Shared context sets. A context set used by several programs changes for all of them. Programs that need stability SHOULD use a frozen or timelocked context set.

  • Linked pages that change or vanish. Rulings use the pinned snapshot, so later edits to the live page change nothing. If the snapshot itself is not retrievable, evaluators cannot attest and the request expires.

  • Pages that cannot be fetched. Pages behind logins or paywalls, or that disallow automated access, SHOULD NOT be linked. Supply the text as inline or external content instead.

  • No eligible evaluators. If no active evaluators match the jury specification and context size, QuoteRuling and RequestRuling MUST fail rather than create a request that cannot be served.

  • Estimates that are wrong. Token counts are capped by max_input_tokens and max_output_tokens, so charges cannot exceed the quote's basis. A shortfall can still arise when extra evaluators or proofs are needed, and is handled by "needs funds".

  • External context not accepted. If ext_context_mode is 0, RequestRuling MUST reject any external context. If it is 2, it MUST reject requests without any.

  • Over budget. If prompt, context and input exceed an evaluator's max_context, that evaluator MUST NOT attest. RequestRuling SHOULD fail if fewer than evaluators listed evaluators can fit context_budget.

  • Compact form drift. If the compact form and the source disagree, the stored bytes are what was ruled on. source_hash lets anyone show the difference.

  • Deadlines. Deadlines are slots. Clients SHOULD allow enough slots for model latency, which is commonly tens of seconds per ruling.

  • Input confidentiality. input_ref may point to encrypted content readable only by the evaluators. The on-chain hash stays public.

Validator Components Affected

None. Each proposal is an interface implemented by an on-chain program using the existing Ed25519 signature-verification precompile. No runtime, virtual machine, consensus or networking change is required. RPC providers, indexers and explorers MAY decode the account layouts defined here.

Alternatives Considered

  • Each application defines its own format. This is the status quo. It works for one application, but calling programs, wallets and explorers cannot interpret results across applications, and every team re-solves replay protection, commit-reveal and content pinning.

  • Immutable versions only. Earlier drafts made every prompt version immutable behind a version pointer. That is safer for callers but costs a new account per edit and slows creators down. Pinned hashes give callers the same guarantee for any single ruling, and creators who want permanence can freeze.

  • General-purpose oracles. Existing oracle networks deliver data and computation results, but do not define natural-language programs, context sets, model commitments, model-family diversity or proofs of inference.

  • Running models on chain. Small networks can run inside a program, but models able to read natural-language rules are many orders of magnitude beyond compute and storage limits.

Impact

  • Dapp developers get one way to store natural-language logic, call it from a program and pay for it.
  • DAOs, treasuries and companies can keep constitutions, policies and standards on chain as context, update them in public, and freeze them.
  • Wallets and explorers can show the exact prompt, context, revision and mutability behind any request, or the hashes alone when content is encrypted.
  • Validators and core contributors are not affected.

Security Considerations

  • Injected instructions in external context. A caller can put text in the external context that tries to steer the models ("approve this"). Evaluators MUST present external context as material to judge, below the internal context, and inference programs SHOULD restrict which kinds callers may add.

  • Manipulated pages. Whoever controls a linked page controls what is captured. A DAO discussion can be edited, or flooded with posts, before the snapshot. Programs SHOULD snapshot at a defined moment, for example when a vote closes, and SHOULD treat linked pages as evidence to weigh, not as rules. Text inside a page MUST be passed to the model as data, never as instructions.

  • Mutable rules. A creator can change the prompt or context to rules that favor them. Pinned hashes protect any single ruling, but not future ones. Calling programs SHOULD check prompt_hash and context_hash against values they trust, or require timelocked or frozen programs, for high-value decisions. Wallets SHOULD show the mutability mode.

  • Encrypted rules cannot be audited. When content is encrypted, users cannot read the rules they are judged by, and any evaluator can leak them. Programs that use encryption SHOULD publish source_hash and SHOULD commit to disclosing the source after a stated time or on dispute.

  • Compact forms can change meaning. Compilation is lossy. Creators SHOULD test compact forms against the source, and disputes SHOULD be able to reference the source.

  • Fee padding. An evaluator could claim more tokens than it used. Charges are capped by pinned prices, the request's token caps and max_fee_each, and output length is checkable against output_hash.

  • Callbacks. Callbacks run in separate transactions and move no funds, so they cannot drain escrow. A callback program must not trust the event alone; it re-reads the ruling.

  • Liveness and censorship. Evaluators may not answer. Expiry yields default_outcome. Programs MUST design that outcome to be the safe one, for example "hold" rather than "allow".

Backwards Compatibility

This proposal adds a new program interface and changes nothing existing.

Conformance

  • A reference program implementing these instructions, with tests on a local cluster for each mutability mode, timelocked staging, freezing, request pinning across content changes, compact, compressed and encrypted content, linked and git content, context-budget checks, external context limits, jury constraints, quotes, escrow, refunds, "needs funds", top-ups and callbacks.
  • Test vectors for the context hash, the external context hash, the encoding pipeline and the key envelope.

Appendix A: Prompt format (informative)

asc: 1
name: <short name>
applies_to: <the kind of input, e.g. withdrawal or proposal_execution>
outcomes:
  <id>: <one-line meaning>
default: <outcome id used on expiry or no quorum>
evidence: [<names of evidence items evaluators may read>]
---
<instructions in natural language, or their compact form>

Evaluators MUST reply in this form, and output_hash covers the whole reply:

{
  "outcome": "<one id from outcomes>",
  "confidence": <0 to 100>,
  "summary": "<the decision in a few sentences>",
  "reasoning": "<why, step by step, applying the context to the input>",
  "sources": [
    { "kind": "context", "content_hash": "<hex>", "locator": "Art. 2, sec. 3" },
    { "kind": "evidence", "content_hash": "<hex>", "locator": "ticket" }
  ]
}

SIMD 2 (draft): Inference Evaluators and Attestations

simd: 'XXXX'
title: Inference Evaluators and Attestations
authors:
  - Rex St. John (Verafy)
category: Standard
type: Interface
status: Idea
created: 2026-11-05
feature: (fill in with feature key and github tracking issues once accepted)

Summary

These SIMDs are part of a broader proposal to bring Inference Programs to Solana natively: Bringing Inference Programs To Solana.

This proposal defines how off-chain model operators take part in inference programs. An evaluator registers an Ed25519 signing key, its prices and a model commitment: a record of exactly which model it runs. For each request it serves, it commits to an answer and then reveals an attestation: a signed message binding the request, the pinned prompt and context, the input, its outcome, its confidence, and an optional reference to a zero-knowledge proof that the committed model produced the output. It also defines three assurance levels, from signatures alone (L0) to verified proofs of inference (L2).

This is one of three companion proposals that bring inference programs to Solana:

  1. Inference Programs: natural-language programs on chain, their context, and how other programs call and pay for them.
  2. Inference Evaluators and Attestations: who runs the models, what they commit to, and the signed, optionally provable, vote each one casts.
  3. Inference Rulings, Disputes and Challenges: how votes become a signed ruling that programs act on, and how rulings are disputed, challenged and overturned.

The motivation, use cases and diagrams for all three are in the overview post.

Motivation

A signature proves which key signed, not which model ran. An operator could quietly swap in a cheaper model, a fine-tuned one, or a person. Recent work on zero-knowledge proofs of LLM inference (Anthropic, 2026) shows that a provider can prove that committed weights produced an output without revealing them. Such proofs are large and slow today (tens of megabytes, seconds to verify, one open model), so they cannot be verified in a transaction, but they can be referenced and checked off chain.

This lets each side do what it is good at: models think off chain on hardware built for it, and Solana keeps a permanent, checkable record of who voted, for what, and with what proof. A common registry and attestation format lets any program trust any evaluator's work across implementations.

Dependencies

This proposal depends on the following proposals, submitted together:

  • SIMD-XXXX: Inference Programs

    Defines the RulingRequest whose pinned hashes and jury specification every attestation answers.

  • SIMD-XXXX: Inference Rulings, Disputes and Challenges

    Counts revealed attestations into a ruling.

New Terminology

  • Evaluator: An off-chain operator that runs a model against inference programs and signs attestations with a registered Ed25519 key.

  • Model commitment: A record of exactly what an evaluator runs: a model identifier, a hash of the weights, a hash of the tokenizer and a hash of the inference configuration.

  • Attestation: An Ed25519-signed message from an evaluator binding a request, the prompt and context hashes, an input hash, an output and a model commitment.

  • Proof of inference: A proof, verified off chain, that a committed model produced a given output. Attestations reference it by hash.

  • Assurance level: How much a ruling proves, from signatures alone (L0) up to verified proofs of inference (L2).

Detailed Design

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

All integers are little-endian. All hashes are SHA-256 unless stated otherwise. Account layouts begin with an 8-byte discriminator equal to the first 8 bytes of sha256("inference-programs:" || account_name).

Accounts

Evaluator

A PDA at ["evaluator", operator].

discriminator        [u8; 8]
operator             Pubkey     // controls this record
signing_key          [u8; 32]   // Ed25519 key that signs attestations
encryption_key       [u8; 32]   // X25519 key for encrypted content
model_commitment     Pubkey     // ModelCommitment account
family               [u8; 32]   // model family label, e.g. "llama-4"
max_context          u32        // largest context the model accepts, tokens
payout_wallet        Pubkey     // where this evaluator's fees are paid
base_fee             u64        // lamports per attestation
input_price          u64        // lamports per 1,000 input tokens
output_price         u64        // lamports per 1,000 output tokens
proof_fee            u64        // lamports for a proof of inference, if offered
status               u8         // 0 active, 1 paused, 2 retired
registered_slot      u64
ModelCommitment
discriminator        [u8; 8]
model_id             [u8; 64]   // UTF-8, zero padded
weights_hash         [u8; 32]
tokenizer_hash       [u8; 32]
config_hash          [u8; 32]   // hash of decoding settings
                                // (e.g. temperature 0, fixed seed)
proof_system         [u8; 32]   // proof-of-inference system id,
                                // all zeros if none
publisher            Pubkey

Model commitments are published once and MUST NOT change. Closed models whose weights cannot be committed MAY use a zero weights_hash. Rulings that rely on them cannot reach assurance level L2.

EvaluatorSet (optional)

A list of evaluator accounts an inference program accepts, controlled by the inference program's authority. It is REQUIRED when the prompt or any context document is encrypted, since only listed evaluators hold keys. Without one, any active evaluator may attest, subject to the request's quorum rules.

Attestation

A PDA at ["attestation", ruling_request, evaluator].

discriminator        [u8; 8]
ruling_request       Pubkey
evaluator            Pubkey
commitment           [u8; 32]   // sha256(message || salt), set at commit
outcome              u8         // set at reveal
confidence           u8         // 0 to 100, the model's own confidence
output_hash          [u8; 32]   // sha256 of the full model output
output_ref           [u8; 96]   // where the full output can be fetched
proof_hash           [u8; 32]   // sha256 of the proof, or zero
proof_verifications  u8         // count of verifier attestations, see L2
revealed             bool

Attestation message

Evaluators sign the following byte string with Ed25519:

"solana-inference-attestation:v1"   // 31 bytes, ASCII, no terminator
ruling_request        [u8; 32]
prompt_hash           [u8; 32]
context_hash          [u8; 32]
ext_context_hash      [u8; 32]
input_hash            [u8; 32]
evidence_hash         [u8; 32]
model_commitment      [u8; 32]      // ModelCommitment account address
outcome               u8
confidence            u8
output_hash           [u8; 32]
proof_hash            [u8; 32]

The domain prefix prevents a signature over this message from being valid for any other purpose. Binding ruling_request prevents replay across requests. Binding prompt_hash, context_hash, ext_context_hash and input_hash means an attestation applies to exactly one prompt, one context set, one external context and one input.

Commit, then reveal

Each evaluator first submits only sha256(message || salt) before commit_deadline. After that slot, the evaluator (or anyone holding the message, salt and signature) calls RevealAttestation. The program MUST check that:

  1. The transaction contains an Ed25519 precompile instruction verifying signing_key's signature over the message. The program reads it with instruction introspection.
  2. The message fields match the request and the evaluator's model commitment.
  3. sha256(message || salt) equals the stored commitment.

No evaluator can see another's answer before committing to its own.

Eligibility

Only active evaluators that match every constraint of a request's JurySpec, whose max_context fits the request's context_budget, and that are in the program's evaluator set when it has one, may commit. Prices are pinned at request time.

Assurance levels

  • L0: signed by quorum registered evaluators.
  • L1: L0, plus commit-reveal and at least quorum distinct model families.
  • L2: L1, plus each counted attestation has a non-zero proof_hash and at least the program's required number of verifier attestations confirming that the proof verifies against the evaluator's model commitment.

Proofs of inference are not verified on chain by this proposal. A verifier is an evaluator-like registered key that signs "solana-inference-proof:v1" || attestation || proof_hash || result. RevealAttestation or a separate AttestProof instruction counts these signatures in proof_verifications. If proof sizes and verification costs fall enough for on-chain verification, a future SIMD can add a syscall and let L2 be checked directly.

Fast evaluators (informative)

A new class of models, sometimes called System 1 models, returns a typed answer (a choice from a list, a score or a yes or no) with a calibrated probability, instead of generated text. One early example reports 70 to 500 milliseconds per decision, at a small fraction of a language model's cost, with lower accuracy than frontier models on the vendor's own benchmark (TypeSafe Jev, 2026). These figures are vendor-reported and not independently reproduced.

They fit this interface in three ways, none of which needs new accounts:

  1. As a screen. A creator publishes a second inference program with the same context set and a prompt that asks one yes-or-no question per rule. A caller requests a ruling from it first. Calling programs MAY act on a screen result only for outcomes that are safe on their own, such as default_outcome, or within value limits they enforce in code, and SHOULD escalate everything else to a full request.
  2. As an evaluator. A System 1 evaluator can attest: its outcome and probability fill outcome and confidence. It cannot be the rapporteur, because it writes no summary, reasoning or sources, so a quorum SHOULD include enough language-model evaluators to post and sign off an opinion.
  3. To size the jury. A client MAY use the screen's probability to choose the full request's JurySpec: a larger jury, or a higher assurance level, when the screen is unsure.

A hosted, closed System 1 model publishes no weights commitment, so it cannot reach L2, and it counts as one model family. Calibrated probabilities are not correct answers. These models are also weaker on numeric checks, which belong in the calling program's own code anyway.

Instructions

  • PublishModelCommitment (signer: publisher): Creates an immutable ModelCommitment.

  • RegisterEvaluator (signer: operator): Creates or updates an Evaluator.

  • CommitAttestation (signer: evaluator signing key): Records the commitment before commit_deadline.

  • RevealAttestation (signer: anyone): Checks the Ed25519 signature and the commitment, records the outcome.

  • AttestProof (signer: registered verifier): Records a verifier's signature that an attestation's proof verifies against the evaluator's model commitment, and increments proof_verifications.

Edge Cases

  • Encrypted content without keys. An evaluator with no KeyWrap cannot read the content and MUST NOT attest.

  • External content mismatch. Evaluators MUST refuse to attest if fetched bytes do not hash to content_hash.

  • Retired evaluators or keys. An evaluator retired after committing MAY still reveal for that request. Its key MUST NOT be accepted for new requests.

  • Too many signatures for one transaction. Each reveal is its own transaction, so quorum size is not limited by transaction size.

  • Empty or malformed outputs. An attestation whose outcome is not in the prompt's outcome list MUST be rejected at reveal.

Validator Components Affected

None. Each proposal is an interface implemented by an on-chain program using the existing Ed25519 signature-verification precompile. No runtime, virtual machine, consensus or networking change is required. RPC providers, indexers and explorers MAY decode the account layouts defined here.

Alternatives Considered

  • Trusted execution environments. Hardware attestations from secure enclaves can show which binary ran. They depend on hardware vendors and have a history of side-channel attacks. A model commitment can carry a TEE attestation in place of, or alongside, a proof of inference. A future revision could add it as an assurance level.

  • On-chain verification of proofs of inference now. Current proofs for large language models are far larger than transaction and account limits allow, and take seconds of multi-core CPU time to verify. That rules out on-chain verification today.

Impact

  • Evaluator operators get one registration and attestation format, usable across applications, with published prices.
  • Calling programs can require diversity of model families, or proofs.
  • Model providers can publish commitments, and prove which model ran without publishing weights.
  • Validators and core contributors are not affected.

Security Considerations

  • Model substitution. Without proofs of inference, an evaluator can run a different model than it committed to. Only L2 rulings address this, and closed models cannot reach L2.

  • Collusion. Evaluators can coordinate. Commit-reveal stops copying within a request but not collusion arranged in advance. Distinct-family requirements, evaluator sets and bonds reduce but do not remove this risk.

  • Self-reported confidence. Confidence is the model's own estimate and is not calibrated. Programs SHOULD weigh agreeing over confidence_mean.

  • Replay. Attestations bind the request address, pinned hashes and input hash. Calling programs MUST check that input_hash matches the exact action.

  • Key compromise. A compromised evaluator key can sign false attestations until retired. Quorums with distinct operators limit the impact of one key.

  • Determinism. Proofs of inference require fixed decoding settings, so config_hash MUST describe them. Outputs that vary across runs cannot reach L2.

Backwards Compatibility

This proposal adds a new program interface and changes nothing existing.

Conformance

  • A reference implementation of these instructions, with tests for commit-reveal with valid and invalid salts, rejection of unlisted outcomes, eligibility checks, distinct-family enforcement and verifier counting.
  • Test vectors for the attestation message: input bytes, keys, expected hashes and expected signatures.

SIMD 3 (draft): Inference Rulings, Disputes and Challenges

simd: 'XXXX'
title: Inference Rulings, Disputes and Challenges
authors:
  - Rex St. John (Verafy)
category: Standard
type: Interface
status: Idea
created: 2026-11-05
feature: (fill in with feature key and github tracking issues once accepted)

Summary

These SIMDs are part of a broader proposal to bring Inference Programs to Solana natively: Bringing Inference Programs To Solana.

This proposal defines the ruling: the signed decision recorded on chain when an inference program's evaluators reach quorum. Like a court opinion, it records the outcome, a summary, the reasoning by hash, the sources used (checked against what the jury was given), how strongly the models agreed, every vote's signature, a co-signed sign-off and any dissents. Programs read it with ReadRuling and act on it. A ruling can be disputed quickly, or challenged at any later time with new evidence, and overturned by a new ruling that compares itself to the original. It is never erased.

This is one of three companion proposals that bring inference programs to Solana:

  1. Inference Programs: natural-language programs on chain, their context, and how other programs call and pay for them.
  2. Inference Evaluators and Attestations: who runs the models, what they commit to, and the signed, optionally provable, vote each one casts.
  3. Inference Rulings, Disputes and Challenges: how votes become a signed ruling that programs act on, and how rulings are disputed, challenged and overturned.

The motivation, use cases and diagrams for all three are in the overview post.

Motivation

When judgment happens off chain today, the chain records the outcome but not the reasoning. A ruling closes that gap: anyone can read what was decided, why, on what sources, and who agreed, and a program can check all of it before it acts.

No ruling should be final forever. Evidence turns out to be forged, sources are corrected, rules change. Courts let a later court overturn an earlier decision, sometimes decades on, while the original stays in the record. Rulings need the same: a way to re-examine a past decision against new data and record the result, without rewriting history.

Dependencies

This proposal depends on the following proposals, submitted together:

  • SIMD-XXXX: Inference Programs

    Defines the inference program and the RulingRequest a ruling answers.

  • SIMD-XXXX: Inference Evaluators and Attestations

    Defines the attestations a ruling counts, and the assurance levels it reports.

New Terminology

  • Ruling request: An account recording a request to run one inference program on one input, with the pinned prompt and context hashes, quorum and deadlines.

  • Opinion: The summary, reasoning and sources of a ruling, written by one agreeing evaluator (the rapporteur) and co-signed by the others.

  • Sign-off: An agreeing evaluator's signature over the opinion, saying it fairly states their decision.

  • Dissent: An optional statement from an evaluator who voted for a different outcome, recorded with the ruling.

  • Certainty: How strongly the models agreed: the share of evaluators that agreed, and their self-reported confidence.

  • Challenge: A request, at any time after a ruling is final, to review it against new evidence, new sources or a claimed error. It is decided by a new ruling that compares itself to the original.

  • Review status: What later review has done to a ruling: none, affirmed, overturned or superseded. The original ruling is never changed otherwise.

  • Prior ruling: A past ruling used as context for a new one, the way a court cites precedent.

Detailed Design

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

All integers are little-endian. All hashes are SHA-256 unless stated otherwise. Account layouts begin with an 8-byte discriminator equal to the first 8 bytes of sha256("inference-programs:" || account_name).

Accounts

Ruling

A PDA at ["ruling", ruling_request], created by FinalizeRuling and completed by PostOpinion and SignOff.

discriminator        [u8; 8]
ruling_request       Pubkey
inference_program    Pubkey
prompt_hash          [u8; 32]
context_hash         [u8; 32]
ext_context_hash     [u8; 32]
input_hash           [u8; 32]
outcome              u8
assurance            u8         // level actually reached
certainty            Certainty
rapporteur           Pubkey     // evaluator who wrote the opinion
summary_len          u16
summary              [u8; 512]  // UTF-8, the decision in a few sentences
reasoning_hash       [u8; 32]   // sha256 of the full reasoning
reasoning_ref        [u8; 96]   // where the full reasoning can be fetched
source_count         u8
sources              [Source; 16]
signature_count      u8
signatures           [Signature; 16]  // one per counted attestation
signoff_count        u8
signoffs             [Signature; 16]  // agreeing evaluators, over the opinion
dissent_count        u8
dissents             [Dissent; 8]
finalized_slot       u64
status               u8         // 0 awaiting opinion, 1 final,
                                // 2 disputed, 3 overturned, 4 upheld
review_status        u8         // 0 none, 1 affirmed, 2 overturned,
                                // 3 superseded, 4 under review
reviewed_by          Option<Pubkey>  // latest Ruling that reviewed this one
review_count         u16

Certainty:
  agreeing           u8         // evaluators that chose the outcome
  answered           u8         // evaluators that revealed
  confidence_mean    u8         // 0 to 100, over agreeing evaluators
  confidence_min     u8

Source:
  kind               u8         // 0 context entry, 1 evidence item,
                                // 2 prompt, 3 external context entry,
                                // 4 prior ruling
  content_hash       [u8; 32]   // must match a pinned context entry,
                                // evidence hash or the prompt
  locator            [u8; 32]   // e.g. "Art. 2, sec. 3", zero padded

Signature:
  evaluator          Pubkey
  signature          [u8; 64]   // Ed25519, by the evaluator's signing key

Dissent:
  evaluator          Pubkey
  outcome            u8
  statement_hash     [u8; 32]
  statement_ref      [u8; 96]

The full reasoning is usually longer than an account should hold, so the ruling stores a short summary inline and the full text by hash and reference. Implementations MAY store the reasoning inline in a Content account and point reasoning_ref at it.

ReviewPolicy

A PDA at ["review-policy", inference_program], set by the program's authority, and subject to its mutability mode.

discriminator        [u8; 8]
inference_program    Pubkey
dispute_parties      u8         // 0 requester, 1 named parties, 2 anyone
challenge_mode       u8         // 0 none, 1 parties only, 2 anyone
challenge_bond       u64        // lamports a challenger locks
challenge_min_evals  u8         // floor on a challenge's jury size
bond_growth_bps      u16        // bond increase per earlier review

Without a ReviewPolicy, disputes are open to the requester only and challenges are not accepted.

Finalization

After reveal_deadline, FinalizeRuling counts revealed attestations by outcome. If at least quorum agree on one outcome, and that quorum meets the program's family and assurance requirements, the Ruling records that outcome. Otherwise the Ruling records default_outcome with certainty.agreeing below quorum. Calling programs MUST treat that as "no ruling".

Opinions, sign-off and the returned ruling

A ruling is more than an outcome. Like a court opinion, it says what was decided, why, on what basis, and who agrees.

  1. Votes. Each evaluator's full output, in the format of Appendix A, contains an outcome, a confidence, a summary, its reasoning and the sources it relied on. Its hash is output_hash, and the attestation records the outcome and confidence.
  2. Rapporteur. After FinalizeRuling counts a quorum, the rapporteur is the agreeing evaluator with the lowest sha256(evaluator || ruling_request). It calls PostOpinion with the summary, the reasoning hash and reference, and the sources. If it does not post within opinion_window slots, the next agreeing evaluator in the same order may.
  3. Sources are checked. PostOpinion MUST reject any source whose content_hash is not the pinned prompt, an entry of the pinned context set, a external-context entry, or an item in the request's evidence. A ruling cannot cite a document the jury was not given.
  4. Sign-off. Each agreeing evaluator calls SignOff with an Ed25519 signature over the opinion message below. The ruling becomes final when at least quorum evaluators have signed off. An evaluator that disagrees with the opinion's wording does not sign off, and if too few sign off before signoff_deadline, the next rapporteur posts a new opinion.
  5. Dissents. An evaluator that voted for another outcome MAY call PostDissent before the ruling is final.

The opinion message is:

"solana-inference-opinion:v1"     // 27 bytes, ASCII, no terminator
ruling                [u8; 32]
outcome               u8
summary_hash          [u8; 32]    // sha256 of the summary bytes
reasoning_hash        [u8; 32]
sources_hash          [u8; 32]    // sha256 over the ordered sources

Wallet signatures. Each evaluator's signing_key is an ordinary Solana Ed25519 keypair, so every vote and sign-off is a wallet signature, visible in explorers and checkable by anyone. Evaluators SHOULD also sign the reveal and sign-off transactions with that key, as fee payer or signer, so the evaluator's wallet appears on the transaction itself. A wallet signature proves which operator stands behind a vote. Which model produced it is shown only by a proof of inference (L2).

Returning the ruling to a program. ReadRuling checks that a ruling is final and matches the expected program, hashes and input, then sets Solana return data to:

ruling                [u8; 32]
outcome               u8
assurance             u8
agreeing              u8
answered              u8
confidence_mean       u8
summary_hash          [u8; 32]

A calling program invokes ReadRuling by cross-program invocation and reads the return data, or reads the Ruling account directly.

Reading a ruling from another program

A calling program reads a Ruling account. It MUST check:

  1. The account is owned by the inference programs program.
  2. inference_program, prompt_hash and context_hash match the rules it intends to apply, and ext_context_hash matches what it injected.
  3. input_hash matches the sha256 of the exact action it is about to take.
  4. certainty.agreeing >= quorum, assurance is at least what it requires, and status is final or upheld, with any dispute window it cares about passed. review_status MUST NOT be overturned, and a program acting now SHOULD NOT act while it is under review. It MAY also require a minimum certainty.confidence_min.

Rulings take seconds to minutes, so the pattern is two-phase. In one transaction, a program or client calls RequestRuling with the exact action encoded as the input. In a later transaction, the program performs the action only if a valid Ruling exists for that input. Programs SHOULD also enforce hard limits in their own code, independent of any ruling, and SHOULD allow only outcomes listed in the prompt to change their behavior.

Disputes

OpenDispute within dispute_window sets the Ruling's status to disputed and references a new RulingRequest against the same pinned hashes and input. That new request SHOULD use evaluators whose model families do not overlap with the original quorum. ResolveDispute records the second request's outcome. If it matches, the status becomes upheld. If a different outcome reaches quorum, the status becomes overturned. If neither, the Ruling falls back to default_outcome.

Challenges and later review

A dispute is quick: it re-judges a fresh ruling on the same evidence, before anyone relies on it. A challenge is for later. Facts come out, evidence turns out to be forged, sources are corrected, or the reasoning looks wrong in hindsight. Courts handle this by letting a later court overturn an earlier decision, sometimes decades on, while the original decision stays on the record. Rulings work the same way.

  1. Opening. If the program's ReviewPolicy allows it, anyone eligible may call OpenChallenge on a final ruling at any time, with no window. The challenger states its grounds and supplies what is new:
    • 0 new evidence: facts that were not available at the time;
    • 1 false evidence: an item the ruling relied on was wrong or forged;
    • 2 error: the rules were misapplied to the evidence as it stood;
    • 3 changed rules: the program's context has since changed, and the question is whether the ruling would stand under the current rules. The challenger locks its challenge_bond and funds the challenge request, like any other request.
  2. What the challenge jury sees. The challenge is a new RulingRequest with kind = 2 and reviews set to the original. It pins the original's prompt, context and input hashes, except under grounds 3, where it pins the current ones. Its external context holds, in order: the original ruling and its full reasoning as a prior-ruling entry, the original evidence, and the new material, labeled as new. Old content must still be retrievable, which is why revisions SHOULD be stored permanently.
  3. Comparison. The request prompt asks the jury to compare: does the original outcome still stand given what is now known? The challenge opinion MUST cite the original ruling, and SHOULD say, for each source the original relied on, whether it still holds, and which new source changed the result.
  4. The jury. It MUST have at least the policy's challenge_min_evals evaluators, and SHOULD share no model family with the original quorum, nor with any earlier review of the same ruling.
  5. Result. ResolveChallenge records the outcome on the original ruling:
    • the same outcome reaches quorum: review_status becomes affirmed;
    • a different outcome reaches quorum: overturned (grounds 0 to 2) or superseded (grounds 3);
    • no quorum: the original stands unchanged. The original's reviewed_by points to the challenge ruling, and review_count increases. Nothing else in the original changes, so its history can always be read back: first ruling, every challenge, and each result.
  6. Bond. If the ruling is overturned or superseded, the bond is returned. If it is affirmed, the bond goes to the program's refund_to, or as the program specifies, so that challenging is not free.

A ruling can be challenged more than once. A later challenge MUST bring evidence or grounds that no earlier review of the same ruling considered: OpenChallenge MUST reject a challenge whose new evidence hashes were all already pinned by an earlier review.

What overturning does. Past actions are settled on chain and are not reversed. Overturning changes what the record says and what programs do next. A calling program decides the remedy in its own code: an insurance program can pay a claim whose denial was overturned, a governance program can flag a proposal executed under a ruling later overturned, and any program reading a ruling for a new action MUST treat an overturned one as no ruling.

Prior rulings as precedent. A context set MAY include past rulings as kind-9 entries, so evaluators can apply earlier decisions to similar cases. Evaluators MUST be told each prior ruling's review_status, so an overturned decision is never applied as if it stood.

Instructions

  • FinalizeRuling (signer: anyone): Counts revealed attestations, records the outcome, certainty and vote signatures, and chooses the rapporteur.

  • PostOpinion (signer: rapporteur): Records the summary, reasoning reference and sources, after checking each source against the pinned hashes.

  • SignOff (signer: agreeing evaluator): Adds a signature over the opinion, and marks the ruling final at quorum.

  • PostDissent (signer: dissenting evaluator): Records a dissent.

  • ReadRuling (signer: none): Checks a final ruling and sets return data.

  • OpenDispute (signer: requester or a party named by the program): Marks the Ruling disputed within the window.

  • ResolveDispute (signer: anyone): Applies the outcome of a linked second request.

  • OpenChallenge (signer: challenger, per challenge_mode): Locks the bond, creates a challenge request against a final ruling with the new evidence and grounds, and marks the ruling under review.

  • ResolveChallenge (signer: anyone): Records the challenge ruling's result on the original, and settles the bond.

  • SetReviewPolicy (signer: program authority): Creates or replaces the program's ReviewPolicy.

Edge Cases

  • No quorum. The Ruling records default_outcome with certainty.agreeing < quorum. Calling programs MUST NOT treat it as an approval.

  • No opinion. If no agreeing evaluator posts an opinion that gathers enough sign-offs before the last deadline, the ruling stays in "awaiting opinion" and calling programs MUST NOT act on it.

  • Long reasoning. Summaries are capped at 512 bytes. Full reasoning is stored by hash and reference, and evaluators MUST NOT sign off on an opinion whose reasoning they cannot fetch.

  • More than 16 sources. The opinion lists the 16 most relied on. The full list stays in the reasoning.

  • Challenge of a ruling under review. Only one challenge per ruling is open at a time. Others wait until it resolves.

  • Challenged content not retrievable. If the original's pinned content or evidence cannot be fetched, the challenge cannot be served and expires, and the bond is refunded.

  • Disputes cost money too. A dispute is a new request, funded by whoever opens it.

Validator Components Affected

None. Each proposal is an interface implemented by an on-chain program using the existing Ed25519 signature-verification precompile. No runtime, virtual machine, consensus or networking change is required. RPC providers, indexers and explorers MAY decode the account layouts defined here.

Alternatives Considered

  • Optimistic resolution with human disputes. Optimistic oracles and decentralized courts use human voters. They are proven and complementary, and could serve as the dispute layer for a ruling. Human resolution is slower and harder to scale to every withdrawal or proposal.

  • Editing or deleting overturned rulings. Simpler to read, but it would erase the record that the original decision was made and acted on, and the reasoning behind it. Append-only review keeps both.

Impact

  • Calling programs get one account to check before acting, with a compact return value.
  • Wallets and explorers can show the decision, reasoning, sources, signatures and full review history of any ruling.
  • Parties to a decision get a standard path to dispute or challenge it.
  • Validators and core contributors are not affected.

Security Considerations

  • Models can be wrong or manipulated. Prompt injection through inputs and evidence, forged evidence and shared blind spots across model families are real risks. In the author's tests, a forged correction placed in the evidence led all ten models tested to the same wrong answer. Calling programs MUST keep hard limits in code, MUST restrict effects to listed outcomes, and SHOULD require dispute windows for high-value actions.

  • Misleading summaries. A rapporteur could summarize unfairly. Sign-off by a quorum of agreeing evaluators, and dissents, limit this. The full reasoning and each vote's output stay available by hash.

  • Made-up sources. Models can cite documents that do not exist. Sources must hash to the pinned prompt, context entries or evidence, so a citation to anything else is rejected on chain.

  • Relitigation. A party that lost can keep challenging, hoping to draw a friendlier jury. Bonds, the requirement for new evidence or grounds, growing jury floors and distinct families for each review limit this. Programs MAY raise the bond with each review of the same ruling.

  • Planted evidence. A challenge's new evidence can be forged as easily as the original's. It is pinned and judged like any other evidence, and can itself be challenged.

Backwards Compatibility

This proposal adds a new program interface and changes nothing existing.

Conformance

  • A reference implementation of these instructions, with tests for quorum and no-quorum finalization, opinions, sign-off and dissents, rejection of sources outside the pinned hashes, ReadRuling return data, disputes that uphold and overturn, and challenges on each ground that affirm, overturn and supersede, including repeat challenges and rejected duplicates.
  • A localnet ledger demonstrating a governance program that executes a proposal only after a final ruling against a DAO constitution, and a later challenge that overturns it.
RSJRex St John
Forward-Looking Statements Notice: Verafy blog articles may contain forward-looking statements regarding Verafy’s future plans, technologies, and market positioning and opinions on possible future achievements. These statements are based on current expectations, predicated on attaining future goals, forecasts, and assumptions that involve risks and uncertainties. Actual outcomes and results may differ materially from those expressed or implied in these statements due to factors such as evolving market conditions, technological challenges, regulatory developments, and other risks beyond Verafy's control. Readers are cautioned not to place undue reliance on forward-looking statements. Verafy undertakes no obligation to update or revise such opinions as a result of later or new information, future events, or otherwise.