Actually Smart Contractsalpha

These SIMDs are part of a broader proposal to bring Inference Programs to Solana natively: Bringing Inference Programs To Solana. All three are drafts, open for discussion in SIMD discussion #724, and are not yet submitted as pull requests.

SIMD 1draftDownload Markdown

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.

The same request can ask for a judgment about the past ("was the milestone delivered?") or a prediction about the future ("will this proposal pass?"). Prediction markets can use both: a forecast request records what independent models expected, and a later resolution request records what happened.

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 L0 ... 4 L3, see Attestations
  min_bond           u64        // least bond per counted evaluator
  accept_tee         bool       // hardware reports may count for L1+, L2
  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.

Evaluator bonds, slashing and challenges to individual votes are defined in the Evaluators and Attestations proposal. A request sets the least bond it accepts with JurySpec.min_bond. Implementations SHOULD also 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 2draftDownload Markdown

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. Because today's proofs are far too large to store or verify on chain, it defines what is stored instead (binding commitments, availability references and bonds), how anyone can challenge a vote by re-execution, proof on demand or hardware report, and an ordered set of assurance levels, from signatures alone (L0) to verified proofs (L2), with on-chain verification (L3) reserved.

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
bond                 u64        // lamports locked, slashable on a proven fault
bond_unlock_slot     u64        // earliest slot a withdrawal can complete
faults               u16        // attestation challenges lost
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
weights_ref          [u8; 96]   // where open weights can be fetched,
                                // zero padded, empty for closed models
runtime_hash         [u8; 32]   // hash of the pinned inference runtime
                                // and kernels, for re-execution
tee_measurement      [u8; 32]   // expected secure-hardware measurement,
                                // 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 L1+ or L2, except through secure hardware (see "Hardware attestation").

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_ref            [u8; 96]   // where the proof can be fetched, or zero
tee_report_hash      [u8; 32]   // sha256 of a hardware report, or zero
proof_verifications  u8         // count of verifier attestations, see L2
challenge            Option<Pubkey>  // open AttestationChallenge, if any
voided               bool       // true once a challenge proves a fault
revealed             bool

AttestationChallenge

A PDA at ["attestation-challenge", attestation].

discriminator        [u8; 8]
attestation          Pubkey
challenger           Pubkey
kind                 u8         // 0 output mismatch on re-execution,
                                // 1 proof demanded, 2 proof invalid,
                                // 3 hardware report invalid
bond                 u64        // lamports the challenger locks
respond_deadline     u64        // slot by which the evaluator must answer
resolve_deadline     u64        // slot by which verifiers must attest
upheld_votes         u8         // verifiers confirming the fault
rejected_votes       u8         // verifiers rejecting it
status               u8         // 0 open, 1 fault proven, 2 rejected,
                                // 3 expired

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]
tee_report_hash       [u8; 32]

An evaluator that will only produce a proof on demand signs a zero proof_hash; its commitment to the output is output_hash, and the proof it later publishes MUST be for that output. 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.

Why proofs stay off chain

A proof of inference shows that committed weights produced an output. It is the strongest evidence of which model ran, and it does not fit on Solana. The one published system for large language models reports figures far beyond every relevant limit (Anthropic, 2026):

Quantity One proof today Solana limit
Size about 18.78 MB 1,232 B per tx
Account to hold it about 18.78 MB 10 MiB per account
Rent to store it about 131 SOL 6,960 lamports per B
Uploading it about 19,000 txs about 1 KB per tx
Verifying it 17 s on 24 threads 1.4M compute units
Models covered one open model any, ideally

The size comes from what is proven: every layer of a model with hundreds of billions of parameters, for every token. Proof systems that need no trusted setup grow with the work they cover, so they suit very large computations but do not produce the constant-size proofs a chain can check cheaply. A ruling with five proven votes would need about 650 SOL of rent, and verifying it would need about five orders of magnitude more computation than a transaction allows.

The problem is not only cost. If the chain cannot check a proof, a proof hash alone proves nothing: an evaluator could post the hash of a proof that does not exist or does not verify. Assurance beyond signatures therefore needs three things in place of the proof itself:

  1. A binding commitment. The output, the model, the runtime and, where one exists, the proof are fixed by hash in the signed attestation, so the evaluator cannot change its story later.
  2. Availability. Whatever is needed to check the vote (the output, the proof, and for open models the weights) MUST stay retrievable from output_ref, proof_ref and weights_ref for at least the program's dispute and challenge windows.
  3. A cost for lying. A bond the evaluator loses when anyone shows, by a check that has one right answer, that the commitment was false.

Precedent (informative)

None of these ideas is new. Each is in production elsewhere:

  • Oracles deliver data to chains with signatures and economic incentives, not proofs. Chain programs trust a quorum of independent, staked operators.
  • Optimistic rollups and optimistic oracles accept a claim unless it is challenged within a window. A single honest challenger is enough, because a false claim can be shown false.
  • Optimistic machine learning (opML, 2024) applies that pattern to model inference: a result stands unless a challenger re-executes it, and a bisection game finds the first step that differs.
  • Proof wrapping in zero-knowledge virtual machines compresses a large proof into a small one by proving, inside a succinct proof system, that the large proof verified. Solana already verifies small Groth16 proofs on chain through its BN254 syscalls (groth16-solana).
  • Confidential GPU computing runs a model inside protected hardware that signs a report of what it ran (NVIDIA). Hosted inference behind such reports is already offered commercially (Phala).

This proposal combines them: diversity and quorum by default, re-execution and bonds for open models, proofs on demand where a proof system exists, hardware reports as an alternative, and on-chain verification once proofs can be wrapped small enough.

Bonds

An evaluator locks lamports in bond with PostBond. A request's JurySpec.min_bond sets the least bond each counted evaluator must hold. WithdrawBond completes only after bond_unlock_slot, which MUST be later than the end of the dispute and challenge windows of every request the evaluator attested, and only if none of its attestations has an open challenge.

Programs SHOULD require that the bonds behind a quorum exceed the value a ruling can move. A ruling that guards more than its quorum can lose is secured by honesty alone.

Attestation challenges

Anyone may call ChallengeAttestation on a revealed attestation before the request's dispute window closes, locking a challenger bond. There are four kinds:

  1. Output mismatch (re-execution). For an open model whose commitment pins weights_ref, config_hash and runtime_hash, the challenger claims that running the committed model on the pinned inputs does not produce output_hash. Registered verifiers re-execute and sign "solana-inference-reexec:v1" || attestation || recomputed_output_hash with AttestReexecution.
  2. Proof demanded. The challenger asks for a proof of an attestation signed without one. The evaluator MUST call PublishProof with proof_hash and proof_ref before respond_deadline. A missing proof is a fault.
  3. Proof invalid. The challenger claims a published proof does not verify against the evaluator's model commitment and output_hash. Verifiers check it and sign with AttestProof.
  4. Hardware report invalid. The challenger claims a hardware report does not verify, does not match tee_measurement, or uses a revoked certificate. Verifiers check it and sign.

ResolveAttestationChallenge counts verifier signatures. Each check has one right answer, so a program SHOULD require a supermajority of a verifier set it trusts, from distinct operators. If the fault is proven, the attestation is marked voided, the evaluator's bond is slashed (a share, set by the program, to the challenger and the rest to the request's refund_to), its faults count increases, and the challenger's bond is returned. Otherwise the challenger's bond goes to the evaluator.

A voided attestation no longer counts. If the ruling it was part of loses its quorum, the Rulings proposal reopens it for review.

Hardware attestation

An evaluator running inside protected hardware MAY include a hash of the hardware's signed report in tee_report_hash and keep the report at output_ref. The report binds the runtime measurement, which MUST equal tee_measurement, and the output. Hardware reports let closed models reach a level above L1 without publishing weights. They move trust to the hardware vendor's keys, and such hardware has a history of side-channel attacks, so a request accepts them only when its JurySpec.accept_tee is set.

Assurance levels

assurance is ordered, so a program can require a minimum:

  • 0, L0 signatures. Signed by quorum registered evaluators.
  • 1, L1 diverse. L0, plus commit-reveal and at least quorum distinct model families.
  • 2, L1+ checkable. L1, plus every counted evaluator holds at least min_bond, and every counted attestation can be checked by an attestation challenge: an open model with pinned weights and runtime, a committed proof system, or, with accept_tee, a hardware report. The request's challenge window has passed with no fault proven.
  • 3, L2 proven. L1+, plus every counted attestation carries a published proof, or with accept_tee a hardware report, confirmed by at least the program's required number of verifier signatures.
  • 4, L3 verified on chain. Reserved for a future proposal that verifies wrapped proofs inside the transaction.

Proofs 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, and AttestProof counts these signatures in proof_verifications. Verifiers check, they do not judge, so their quorum is about availability and honesty, not diversity of opinion.

Path to on-chain verification

On-chain verification becomes possible when a proof of inference can be wrapped into a succinct proof of a few hundred bytes that Solana's existing BN254 syscalls verify within a transaction's compute budget. Wrapping an 18 MB proof is itself a large proving job that has not been shown for model inference. When it is, a future proposal can define L3 and an instruction that accepts a wrapped proof in place of verifier signatures, with no change to the attestation message.

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.

  • PostBond and WithdrawBond (signer: operator): Lock lamports as the evaluator's bond, or withdraw them after bond_unlock_slot with no open challenges.

  • ChallengeAttestation (signer: anyone): Opens an AttestationChallenge of one of the four kinds and locks the challenger's bond.

  • PublishProof (signer: evaluator signing key): Answers a proof demand with proof_hash and proof_ref.

  • AttestReexecution (signer: registered verifier): Records the output hash a verifier obtained by re-running the committed model.

  • ResolveAttestationChallenge (signer: anyone, after the deadlines): Counts verifier signatures, voids the attestation and slashes the bond on a proven fault, and settles both bonds.

  • 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

  • Non-deterministic hardware. Two GPUs can produce different floating point results for the same model. Re-execution challenges are valid only when runtime_hash pins kernels and settings that make outputs reproducible, and verifiers MUST run that exact runtime. Without such a runtime, an open model is checkable only by proof.

  • Proofs or outputs that vanish. If a challenged evaluator's output_ref or proof_ref cannot be fetched before respond_deadline, that is a fault.

  • Verifiers that disagree. If neither side reaches the required supermajority before resolve_deadline, the challenge expires, both bonds are returned and the attestation stands.

  • Revoked hardware certificates. A report signed under a certificate revoked before the report's slot is invalid.

  • 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

  • Unchecked proof hashes. A hash of a proof that does not exist, or does not verify, looks the same on chain as a real one. Only availability, challenges and bonds give a proof hash meaning. Programs MUST NOT treat a non-zero proof_hash alone as evidence.

  • Under-bonded quorums. If the value a ruling moves exceeds the bonds behind its quorum, evaluators can profit from a false vote even when they lose their bonds.

  • Verifier collusion. Verifiers that collude can void honest votes or protect false ones. Programs SHOULD use verifier sets with distinct operators and require a supermajority.

  • Griefing. Challengers lock a bond that is forfeited when they lose, so frivolous challenges cost them money.

  • Proofs show the model, not the truth. A proof or report shows which model produced an output. It does not show the output is right: a forged document in the evidence fools a proven model as easily as an unproven one.

  • 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, bonds and withdrawals, and each kind of attestation challenge, upheld, rejected and expired, with slashing and bond settlement.
  • Test vectors for the attestation message: input bytes, keys, expected hashes and expected signatures.

SIMD 3draftDownload Markdown

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.

The same record serves predictions. A prediction market can store what independent models forecast before an event, and resolve the market later with a second ruling on what happened.

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.

Predictions and prediction markets (informative)

A ruling can record a prediction as well as a judgment. The prompt asks about a future event and lists its outcomes, for example yes and no, or ranges of a number. Each evaluator's confidence is then its probability for the outcome it chose, and the ruling's certainty records how many models agreed and how sure they were. Because the ruling is finalized at a known slot and votes are committed before they are revealed, it is a public, timestamped record of what independent models forecast, before the event.

A prediction market uses two inference programs:

  1. Forecast. Before the market closes, the market program, or anyone, requests a forecast with the market's question as the request prompt and the available evidence (news, filings, a forum thread, snapshotted) as external context. The ruling is stored as a record. A market MAY display it, use it to seed prices, or pay for it like any other request.
  2. Resolution. After the event, the market requests a resolution ruling from a resolver program whose internal context holds the market's resolution rules: what counts, which sources decide, and what happens if they disagree. The external context holds the sources. The market pays out only on a final resolution ruling for that market's input, after its dispute window, and a later challenge can overturn a resolution on new or false evidence.

A program can score forecasts by reading both rulings: the forecast's outcome and confidences against the resolution's outcome. Scores belong to the scoring program; this proposal does not define them.

Forecast and resolution SHOULD be different inference programs, and the resolver's jury SHOULD NOT be told the forecast, so a resolution is not anchored to it. Models know nothing after their training data unless the external context supplies it, so forecast requests SHOULD include current evidence and MUST NOT be treated as more than the models' estimate. Anyone who controls a linked page can try to move a forecast or a resolution; the snapshot, injection and challenge rules of these proposals apply.

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.

Voided votes. If an attestation counted in a ruling is voided by an attestation challenge (Evaluators and Attestations proposal), the ruling is recounted without it. If it keeps its quorum, assurance is lowered if needed and nothing else changes. If it loses its quorum, its review_status becomes under review, programs MUST NOT act on it, and a new request with a fresh jury decides it like a challenge on grounds 1.

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.

  • Market manipulation. A party with a position in a prediction market can try to steer its forecast or resolution through the pages it links or the sources it supplies. Resolvers SHOULD name their deciding sources in internal context, snapshot them at a defined time, and allow challenges.

  • 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.