Home / Docs / Architecture / API / Development / Operations / Regression / Config
Raiko2 is a Shasta proof service for Taiko. It builds canonical guest inputs from RPC data, validates them, runs local or remote proving routes, and exposes a typed v4 API for asynchronous proposal-side proof requests.
- Typed v4 proposal-side proof endpoint
- Canonical routes:
native/local,risc0/local,risc0/network,sp1/local,sp1/network - Default binaries include RISC Zero local/network proving and SP1 proving
- Optional remote SGX routes for configured external prover providers
- Shasta-first pipeline for preflight, validation, proving, and aggregation
- Config-driven RPC pair allowlist and optional L1 beacon overrides via
rpc.pairs - Exactly one live instance per isolated runtime namespace; replacements never overlap
- GCS for durable operation or explicitly opted-in ephemeral memory mode, with no cross-namespace data sharing
- In-process queue projected from the namespaced runtime store
Run the fixture-backed server for a dependency-free local API smoke test:
cargo run -p raiko2 --features fixture-server -- fixture-server --host 127.0.0.1 --port 8087Use this only for local API-surface smoke testing, request/response contract checks, and simple task/report workflow validation when you do not want real RPC or prover dependencies. It is not a substitute for preflight correctness, remote-provider integration, or full proposal regression.
Run the real server with an explicit config file:
cp config.example.toml config.toml
$EDITOR config.toml
export RAIKO2_BOUNDLESS_SIGNER_KEY="replace-with-boundless-signer-key"
cargo run -r -p raiko2 -- --config config.tomlconfig.example.toml is a combined production sample. Before running, keep only the desired
per-proof-type tables enabled and fill every setting, credential, and endpoint they require. For
example, SP1 network proving requires prover.sp1.enabled = true, prover.sp1.prover = "network",
and NETWORK_PRIVATE_KEY, while RISC0 network proving requires prover.risc0.enabled = true,
prover.risc0.runner = "network", and real nested Boundless credentials.
Configuration is loaded from --config or RAIKO2_CONFIG. CLI flags and environment variables
override values from the file. The real server checks configured RPC endpoints and hosted prover
capabilities before it starts. The prover loads guest ELF files from RAIKO2_GUEST_ELF_DIR when set,
otherwise from crates/guests/elf. For unreleased testing, build ELFs locally with
just build-guest all. Packaged deployments can download released ELF assets with
cargo run -r -p xtask -- download-guest-elves --tag <tag> --dir <guest-elf-dir>.
A config file can keep a sensitive string outside version control by using an explicit environment reference:
[prover.risc0.boundless]
signer_key = { env = "RAIKO2_BOUNDLESS_SIGNER_KEY" }
[[server.acl.keys]]
id = "submit"
key = { env = "RAIKO2_SUBMIT_API_KEY" }
allow = ["prover.submit"]Raiko2 resolves only a singleton { env = "NAME" } table before schema validation. Missing,
non-Unicode, or empty variables fail startup without printing their values; Raiko2 does not perform
shell expansion or partial-string interpolation. This lets Kubernetes keep the public TOML in a
ConfigMap and inject only keys through a Secret-backed environment variable. If a file with an
environment reference has a schema error, Raiko2 also redacts the decoder details.
This README is the normative source for Raiko2 architecture and operator workflow. The detailed Architecture and Operations documents expand this contract; if they conflict with this section, this README governs.
The runtime is governed by these invariants:
- The configured runtime-state repository is authoritative for task state, artifact registration, and remote submission checkpoints. The in-process queue is an execution projection of that state.
- Each
(runtime.environment, runtime.namespace)has exactly one live process. Replacements never overlap, and the application has no distributed owner lease, owner epoch, or ownership heartbeat. - Namespaces are isolated persistence domains. They never share tasks, artifacts, checkpoints, or invalidation markers, although roots inside one namespace may reuse one canonical artifact.
- The namespace fence is the single process-wide mutation authority. Entering
Drainingcloses admission and readiness immediately, rejects new ordinary mutations and external writes, and waits only for short repository commits plus request-ID checkpoints covered by provider permits acquired whileActive. One namespace-fence permit spans each admitted repository write or proof-object operation so draining can wait for that operation to settle. A separate process-local lifecycle transition gate serializes one short active-root transition across its runtime-state CAS and in-memory queue attach or detach. Neither mechanism spans a complete task, provider call, or publication saga, and shutdown does not wait for every proof task to finish. - Proof computation is not task completion. Completion requires a normalized proof to be durably published, registered, readable, and synchronized to the runtime root.
- Proof manifests are create-only and first-valid-wins. Content is immutable and addressed by SHA-256; invalidation binds to one manifest generation and content hash.
- Remote proving resumes a request identifier only after its submission checkpoint is durable. Request-level retry settings may lower, but never raise, operator-owned limits.
- Durable deployments use separate state and proof-object repository semantics over one configured
GCS namespace; memory mode is explicitly ephemeral and requires an opt-in outside local
environments. The service does not dual-write or automatically fail over between backends.
runtime.startup_cleanupoptionally invalidates activeproofandpreflightmanifests in one non-overlapping namespace before initialization. It preserves immutable content for GCS lifecycle cleanup and is never an automatic recovery or failover mechanism. - A replacement starts only after the old process has stopped admissions, completed its bounded fence drain, stopped and joined workers, and exited. The drain does not wait for all proof tasks; deployment configuration must enforce the non-overlapping replacement sequence.
- Each runtime task lifetime has an immutable
incarnation_id. ExactTaskLifetimepreconditions reject delayed worker, cancellation, cleanup, and publication callbacks after a replacement reuses the same deterministic task ID. A task lifetime is stale-callback identity, not a namespace owner epoch, lease, or distributed lock.RuntimeTaskRecord.artifact_refsis the only durable proof-reference index; metadata is decoded only after its network, pipeline, route, proof type, and derived artifact references match that canonical record. Every persisted proposal carries its canonical engine request directly; derived proposal fields and task references are validated projections, never recovery inputs or compatibility fallbacks. Every root has one mandatory, non-empty request fingerprint, unique within the runtime namespace; anonymous task registration is not supported. - Each scheduler lease also carries a non-reused local token. This prevents remove/recreate ABA from accepting an old completion even when task ID, worker label, and attempt number repeat. The token identifies one local execution attempt and never authorizes runtime writes.
- The in-process execution projection atomically attaches a complete task graph to a root owner and atomically detaches that owner. Shared stages remain executable while any live root owns them; the last owner leaving cancels or removes the stage. Proposal nodes have root-independent definitions and no proposal-to-proposal dependency; aggregation alone depends on the proposal artifacts it consumes. Cancellation and terminal failure first persist the exact root transition, then remove its owner before another root can reuse the stage. A terminal worker error remains queue-retryable until that runtime transition is durable. Runtime state remains authoritative if projection removal fails, and a matching client request rebuilds an inactive projection instead of rolling state back. Startup restores persisted state without attaching proof work. Recovery, destructive retirement, and root replacement compare the complete observed runtime-task snapshot; a stale request performs no queue effect, and replacement commits one successor before swapping its owner projection. Publication checkpoints persist their typed owner/hash intent before materializing the pending blob, so a failed state CAS cannot create an untracked object and a failed object write remains retryable from durable state. Final activation briefly refreshes owners under the local lifecycle gate: a newly registered distinct root may share the proof, while a replacement incarnation for a checkpointed task ID may not. Pending-publication records retain their typed artifact identity until unowned object cleanup succeeds, so restart can finish a replacement interrupted after the runtime CAS.
- Cross-domain lifecycle work is coordinated by the concrete
ProofLifecycleservice as state-first, idempotent effects. Repository commands use exact task lifetimes and artifact descriptors and return typed outcomes such asApplied,AlreadyApplied,Stale,BlockedByLiveOwner,Missing, orConflict; no full-span cross-component lock is used.
The detailed runtime lifecycle, publication transaction, recovery flow, and deployment sequence are illustrated in Architecture.
Preflightresolves canonical Shasta inputs from L1 and L2 RPC.Validationchecks request invariants and witness-derived data.Proverruns the selected backend and runner.Aggregatecombines proposal proofs when the request asks for it.
flowchart LR
RPC["L1/L2 RPC"] --> PF["Preflight"]
PF --> VA["Validation"]
VA --> PR["Prover"]
PR --> AG["Aggregate"]
PR --> API["Task API"]
AG --> API
- V4 is the active public API. Legacy v3 and
/proof/*compatibility routes are not mounted by the server while clients are using v4. - The legacy v3 contract remains documented and covered by compatibility tests while the code is still present.
- Single-proof aggregation is allowed for compatibility with existing
raikoclients. - Shasta manifests support
blob_proof_type = "proof_of_equivalence"only; legacykzg_versioned_hashmanifests are rejected. - Public batch request proof types are
native,risc0,sp1,sgx,sgxgeth, and admission-timezk_anyfor proposal sampling. V4 acceptsnativefor smoke tests and regression whenprover.native.enabled = true; it always resolves tonative/local. - Hosted SP1 proposal proving emits Compressed proposal artifacts and SP1 aggregation emits Plonk
final proofs. A standalone SP1 proposal may therefore complete with
proof = nullwhile its readable artifact carriesquote,input,uuid, andextra_data; aggregate completion always requires a separate artifact with a non-null finalproof. proof_type=risc0resolves to the server's configured RISC Zero prover type. Theprover_type=networkpath submits to Boundless and exposes Boundless quote metadata; Boundless is not a separate proof type.proof_type=boundlessis not accepted; useproof_type=risc0with the server configured forrisc0/networkwhen targeting Boundless.
native/localexecutes the proving pipeline locally and returns public inputs instead of a zk proof.risc0/localgenerates RISC Zero proofs locally.risc0/networksubmits RISC Zero proving directly to Boundless from theraiko2process.sp1/localandsp1/networkselect the SP1 pipeline. The taskprover_typereports whether SP1 ran inmock,local, ornetworkmode.sgx/remotesubmits Shasta proving to the dedicated remote SGX runtime. This repo now shipsraiko2-sgx-proverforproof_type=sgx; that runtime can run inteeornativemode without changing the remote API.proof_type=sgxgethis served by an external remote prover implementation such asgaiko2over the same remote protocol.docker/docker-compose.sgx.regression.ymlstarts both SGX remote services and can optionally add a dockerizedraiko2for regression work.
raiko2 owns the canonical remote prover request fixtures under:
tests/fixtures/remote_prover/shasta_aggregate_request_v1_single_fixture_proof.json
The aggregate request fixture is the strict protocol golden for:
raiko2-shasta-aggregate-request-v1
Run the ignored black-box conformance harness against a provider endpoint with:
RAIKO2_REMOTE_PROVER_BASE_URL=http://127.0.0.1:8080 \
cargo test -p raiko2-prover --no-default-features \
--test remote_prover_conformance -- --ignored --nocaptureThe harness builds the proposal request from the shared Shasta GuestInput fixture and posts it to:
POST /prove/shasta
This harness targets providers whose /prove/shasta input is the v1
raiko2-shasta-request-v1 packet with payload.guest_input. raiko2-sgx-prover consumes the
same request shape and runs the Shasta guest validation path before signing.
It then builds a live aggregate request from the returned proposal proof and posts that derived request to:
POST /prove/shasta-aggregate
This keeps aggregate conformance provider-agnostic while preserving provider identity continuity for implementations that require aggregate subproofs to come from the current prover instance.
The harness verifies the provider returns a raiko2-proof-v1 envelope with an input value that
is self-consistent with the submitted proof carry data.
For the first external provider migration, see
docs/gaiko2-remote-prover-integration.md.
bin/raiko2: HTTP server and CLIcrates/pipeline: preflight, manifest building, and validation wiringcrates/prover: prover backends and aggregation adaptersxtask: guest build, verifier registration, benchmarking, and release automation
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
Some files are derived from third-party projects and may include their own copyright and license notices; those file-level terms apply.
