The Oracle Interoperability Protocol: message semantics, state transitions, routing, validation, errors and conformance rules for state-machine implementations.
Documentation | Specification | Quickstart | Architecture | Formal verification | Assurance | Changelog
Unaudited. Not for production. OIP v0.6.2 is a prototype-stage specification. The Rust and Go code here makes its rules executable and testable. Isabelle/HOL proofs cover models of the protocol under stated assumptions, and the required CI check holds the Rust and Go code to models exported from those proofs on fixed and seeded inputs (Formal verification). That is not a proof about every run of the compiled code. The code has had no security audit, and this repository describes no deployment.
A transfer, a lock or a regulatory order often has to change state in two places at once: on a chain and in an off-chain system that keeps its own records. Each side learns about the other through messages, and messages can arrive late, twice, out of order or from the wrong sender. Two implementations can also read the same bytes differently. When either happens, one side records an effect that the other never sees.
OIP defines one signed message format and the checks a receiver applies before anything changes: the sender's key and scope, the protocol version both peers negotiated, the message lifetime, duplicate detection and the layout of each operation. Accepted calls end in recorded outcomes that the caller can read again after a timeout or a crash, so a retry returns the earlier result and does not repeat the effect.
Both sides can check the result. A caller verifies a signed response against the request it kept, and shared test vectors hold implementations in different languages to the same results. This repository contains the rules, the vectors, a Rust reference implementation and a Go implementation of the message layer.
You need rustup and Go 1.25.5. The generated-code check also needs Python 3, protoc 33.5 and protoc-gen-go v1.36.8, as described in CONTRIBUTING.md.
git clone https://github.com/Oraclizer/oip-spec.git
cd oip-spec
rustup toolchain install 1.96.1 --profile minimal
cargo +1.96.1 test --locked
(cd go && go test -mod=readonly ./...)Both test commands report ok. The Rust suite runs the reference against the
vectors in tests/vectors/. Tests that need live etcd
clusters, mutual TLS stores or recorded archives are marked ignored. List
them with:
cargo +1.96.1 test --locked -- --list --ignoredRust and Go apply the nine checks in the order of the transport receive table. The Rust reference then admits the request for the state owner, which checks caller authority, trusted time and any retained result before the operation runs (persistent request admission). Caller identity, keys, reference time and durable storage come from adapters that the deployment supplies; this repository does not verify them.
The schema in proto/oip.proto generates the Rust
bindings in src/wire/generated.rs and the Go bindings in go/wirepb/.
Both implementations check the original bytes before the generated parser
reads them, so duplicate fields, unknown fields and competing alternatives
are refused before they can be normalized. The word layout of every
operation is in spec/operations.md.
| Version | Defined in | Treatment in this repository |
|---|---|---|
| v0.6.2, wire version 6 | spec/ and proto/oip.proto |
Adds configured THRESHOLD envelope verification with the current registered quorum |
| v0.6.1, wire version 6 | v0.6.1 release | Adds state commitment synchronization and accepts Write in the Ed25519 reference profile |
| v0.6.0, wire version 6 | v0.6.0 release | Earlier version 6 operation set and matching vectors |
| v0.5 | OIP v0.5 documentation | Used only with an authenticated, permitted legacy peer and an explicitly configured codec for the common Query and Heartbeat operations. The codec is a reference compatibility record and does not interoperate with the wire format in the published v0.5 documentation |
| Any other version | Refused with UNSUPPORTED_VERSION. Parse, signature, timeout and rejection errors never select another version |
The Ed25519 reference configuration accepts 28 of the 33 operations when both
commitment operations are enabled. A known operation excluded by the selected
configuration receives UNSUPPORTED_VERSION before admission. The
reference configuration lists
them.
| Component | Pinned version |
|---|---|
| Rust | 1.96.1, edition 2024; dependency versions pinned in Cargo.toml and Cargo.lock |
| Go | 1.25.5 with google.golang.org/protobuf v1.36.8 |
| Code generation | protoc 33.5 and protoc-gen-go v1.36.8 |
A SINGLE signature uses the authenticated peer's Ed25519 key. A configured
THRESHOLD signature carries an ordered list of member signatures over the
same Core and requires the current registered quorum. See the
threshold envelope rules.
The formal models for OIP live in the
Oracle_Interoperability_Protocol
folder of Oraclizer/formal-verification. They connect to this repository in
three ways:
- Proofs about models. Isabelle/HOL sessions model the product, the reference profile, record reopening, the recovery boundary and the message interfaces. The v0.6.1 and v0.6.2 extension sessions add synchronization, Write, threshold signatures and further product, storage and message rules, with their executable interfaces. Each theorem holds under the assumptions it names.
- Source correspondence. Named statements relate selected Rust operations to the models. They are maintained by hand; no tool derives them from the compiled code.
- Executable comparisons. Models exported from the checked theories run
unedited in CI. Three lock files pin each exported file by SHA-256 and Git
blob:
model-artifact.lock.jsonfor the typed transport model,wire-response-artifact.lock.jsonfor the full response model andthreshold-raw-artifact.lock.jsonfor the threshold signature step. The required Tests result check fails unless:- Rust, Go and the typed transport model agree on all seven recorded fields for 692 inputs, 180 fixed and 512 seeded (wire value comparison);
- Rust and the full response model agree on 261 inputs: 33 original operations, 207 typed results and 21 client inputs (response comparison);
- Rust, Go and the checked threshold signature step agree on 22 THRESHOLD packets: the verdict, the selected group, the signers, the Core and the signing preimage. The attestation and binding effects of these packets are checked separately, against a fixed rule in the comparison script (threshold comparison).
In the other direction,
consumer-binding.json
in the proof repository lists the exact oip-spec commit and the model pins,
and its
REPRODUCING.md
explains how to rebuild the sessions and the exports.
The exported models carry a fingerprint of the runtime sources listed in
tests/runtime-source-files.json. Changing
one of those files fails the comparison until a model with the new fingerprint
is exported and pinned;
CONTRIBUTING.md
explains what that means for a pull request. The
artifact contract and the
pinned Linux recipe give the details.
The required check does not compare financial or internal product state with a model; the source regression interface keeps those source observations separate.
The comparisons cover the listed inputs. They are not a proof that every run of the compiled Rust or Go code matches the models. The compiler, the cryptographic primitives and the identity, source attestation and storage providers remain assumptions.
| Check | Command | A pass shows |
|---|---|---|
| Rust reference tests | cargo +1.96.1 test --locked |
The reference produces the expected results and refusals, including on the shared vectors. Ignored tests are listed in the log and not run |
| Go tests | go test -mod=readonly ./... in go/ |
The Go message layer decodes, checks and refuses the vector frames as specified |
| Generated bindings | python3 scripts/generate-wire.py --check with the pinned generators |
The committed Rust and Go bindings are byte-identical to the pinned generators' output |
| Operation table | python3 scripts/render-operations.py --check |
spec/operations.md matches its source table |
| Operation conformance | python3 scripts/check-operations.py |
Rust, Go and the pinned typed model agree on all seven recorded fields across 692 inputs. Missing or stale model inputs fail the check. |
| Signed interoperation | python3 scripts/test-wire-interop.py |
Rust and Go exchange signed frames, including execution at the Rust persistent authority |
| Response comparison | python3 scripts/check-response-boundary.py after the source runs in tests.yml |
Rust's signed responses and client results agree with the pinned full response model on 261 inputs |
| Threshold signature comparison | python3 scripts/check-threshold-raw.py with the Poly/ML runtime and output folder used in tests.yml |
Rust and Go receive 22 THRESHOLD packets with the same verdict, selected group, signers, Core and signing preimage as the pinned checked signature step |
| Repository health | node .github/scripts/verify-repository-health.mjs |
Links, vector checksums, workflow pins and public-text rules hold |
| Formal models | Proof source and scope | The proof repository lists the Isabelle/HOL sessions and each theorem's assumptions. |
A hosted result applies to the commit it ran on. The checks do not establish:
- an independent security audit;
- a deployment, an operator procedure or a key-management process;
- the behavior covered by tests that need live services, because CI does not run them;
- a proof that every run of the compiled Rust or Go code matches the formal models. The model comparisons cover the listed inputs, and the source correspondence covers selected Rust operations and is maintained by hand;
- any legal or regulatory fact. Regulatory operations carry decisions made outside the protocol, and OIP checks and records those decisions.
| Document | Covers |
|---|---|
| Common product model | Request identity and binding, crash and recovery, interleaving |
| Message format and version profiles | Version negotiation, the signed message, admission and retry, responses, field numbers and operands |
| Operation operands | Word layout of all 33 operations, generated from operations.json |
| State commitment synchronization | Version 6 operation additions, source attestations and current commitment reads |
| Response code allocation | Assignments, compatibility and retry rules for new results |
| Lock and finality rules | Lock ownership, source attestations, pending amounts and terminal evidence |
| Identity and ownership handover | Caller and endpoint identity, Ed25519 reference keys, owner and session handover |
| Threshold envelope signatures | Current group selection, the scheme 2 signature field, admission and retries |
| Persistence and recovery | Durable commits, the etcd control transport, archive selection, retained results and unresolved effects |
| Outcomes and publication | Call identity and completion, consumption of original events, publication and settlement |
| Current and historical reads | Current and historical observations |
| Regulatory execution | Trusted reference time, regulatory entry and spending under a completed freeze |
| Compatible service actions | When two actions may run in either order with the same state and replies |
| Path | Purpose |
|---|---|
spec/ |
Normative rules, one document per topic, and the operation table with its schema |
proto/oip.proto |
Message schema; the Rust and Go bindings are generated from it |
src/ |
Rust reference: product boundary, message layer, recovery and handover profiles |
examples/wire_corpus.rs |
Prints the signed message corpus used to compare Rust and Go |
go/ |
Go message layer: byte checks, admission, operands, the v0.5 compatibility codec and a corpus generator |
tests/ |
Shared test vectors with SHA-256 checksum files, the pinned model locks and the model comparison contracts |
scripts/ |
Binding generation, operation-table rendering, the Rust and Go exchange and the model comparisons |
docs/assets/ |
README banner, diagrams and social preview |
.github/ |
Workflows, the repository health checker, and issue and pull request templates |
- Report suspected vulnerabilities privately through SECURITY.md. Do not disclose exploit details in a public issue.
- CONTRIBUTING.md explains which changes are welcome, the local checks and how long they take.
- SUPPORT.md separates usage questions from defects and security reports.
- GOVERNANCE.md records who decides and how changes merge.
- Participation follows the Code of Conduct.
Licensed under the Apache License 2.0. Copyright Oraclizer Labs, Inc.
DISCLAIMER.md summarizes the research, deployment and legal boundaries in plain language. Cite the specification with CITATION.cff and name the commit you used.
Maintainer: Jinwook Kim (Jay), jay@oraclizer.io.