Skip to content

feat: add oracle-url field to orders spec#45

Open
hardyjosh wants to merge 6 commits intomainfrom
feat/oracle-url-spec
Open

feat: add oracle-url field to orders spec#45
hardyjosh wants to merge 6 commits intomainfrom
feat/oracle-url-spec

Conversation

@hardyjosh
Copy link
Contributor

@hardyjosh hardyjosh commented Feb 16, 2026

Motivation

Orders that require external data (e.g. price feeds) at take-time currently have no way to advertise their oracle endpoint in the YAML config. This adds the spec for it.

Changes

Adds an optional oracle-url field to the orders section of the ob-yaml spec. When present, tooling encodes a SignedContextOracleV1 metadata item (magic 0xff7a1507ba4419ca) into the order's RainMetaDocumentV1, enabling oracle endpoint discovery by takers and indexers.

Includes:

  • Field documentation
  • Oracle server response format spec (SignedContextV1 JSON)
  • Example YAML showing an order with oracle-url

Context

Part of the signed context oracle integration:

  • rain.metadata#92 — metadata type
  • rain.interpreter#427 — submodule bump
  • rain.orderbook#2457 — SDK parsing
  • rain.orderbook#2458 — fetch + wiring
  • rain.orderbook#2459 — UI
  • rain-oracle-server — reference server implementation
  • This PR — YAML spec
  • Next: rain.orderbook YAML parsing (Phase 6)

Summary by CodeRabbit

  • Documentation
    • Added an optional oracle-url field for orders and an example oracle-order demonstrating usage.
    • Introduced a Signed Context Oracle spec describing the POST API, response format (signer, context, 65-byte signature), signing/verifying steps, error responses, and expected encodings.
    • Documented on-chain discovery of oracle endpoints via order metadata and provided security/integration guidance.

Orders can now specify an optional oracle-url that points to a signed context
oracle server. When present, tooling encodes a SignedContextOracleV1 metadata
item into the order's RainMetaDocumentV1, enabling oracle discovery by takers
and indexers.
@coderabbitai
Copy link

coderabbitai bot commented Feb 16, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds an optional oracle-url front-matter field to orders and a new Signed Context Oracle specification. Tooling encodes a RaindexSignedContextOracleV1 metadata item into RainMetaDocumentV1 when oracle-url is present; the spec defines the POST request/response, signature scheme, context encoding, and security model.

Changes

Cohort / File(s) Summary
Orderbook front-matter & docs
ob-yaml.md
Adds optional oracle-url to order front matter, documents the Signed Context Oracle usage, includes an oracle-order example, and notes that tooling will encode a RaindexSignedContextOracleV1 metadata item (magic 0xff7a1507ba4419ca) into RainMetaDocumentV1 for on-chain discovery.
Signed Context Oracle spec
signed-context-oracle.md
New spec defining a Signed Context Oracle protocol: a POST endpoint accepting ABI-encoded (OrderV4, uint256 inputIOIndex, uint256 outputIOIndex, address counterparty) and returning JSON { signer, context: bytes32[], signature } where signature is EIP-191 over keccak256(abi.encodePacked(context[])). Specifies canonical types, context encoding (DecimalFloat layout), error formats, signing/verification flow, on-chain discovery via RainMetaDocumentV1 metadata, and security considerations.

Sequence Diagram(s)

sequenceDiagram
  participant Order as Order Front Matter
  participant Chain as RainMetaDocumentV1 (On-chain)
  participant Consumer as Consumer / Indexer
  participant Oracle as Signed Context Oracle Server

  Order->>Chain: encode RaindexSignedContextOracleV1 metadata (includes oracle-url)
  Consumer->>Chain: read order metadata (discover oracle-url)
  Consumer->>Oracle: POST ABI-encoded (OrderV4, inputIOIndex, outputIOIndex, counterparty)
  Oracle-->>Consumer: 200 JSON { signer, context[], signature }
  Consumer->>Consumer: verify EIP-191 signature over keccak256(abi.encodePacked(context[]))
  Consumer->>Chain: use verified context for order evaluation/indexing
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add oracle-url field to orders spec' accurately describes the main change: adding an optional oracle-url field to the orders specification. The title clearly captures the primary objective and is specific and concise.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/oracle-url-spec

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

hardyjosh pushed a commit to rainlanguage/rain.orderbook that referenced this pull request Feb 16, 2026
Adds optional oracle-url field to OrderCfg, parsed from the YAML front
matter orders section. When present, this URL identifies a signed context
oracle server for the order.

Changes:
- Add oracle_url: Option<String> to OrderCfg struct
- Parse oracle-url via optional_string in YAML parsing
- Add oracle-url to ALLOWED_ORDER_KEYS
- Update Default and PartialEq impls
- Add test for oracle-url parsing (present + absent)

Spec: rainlanguage/specs#45
Chained on: #2459 (Phase 4)
The signed context is provided by the caller during take/clear, not
just 'at take-time'. Updated wording to be precise about the usage
context.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@ob-yaml.md`:
- Around line 285-292: Update the Oracle URL documentation to state transport
and security expectations: require HTTPS for the `oracle-url` to prevent
downgrade/MITM, recommend servers use TLS with valid certificates, and document
that endpoints encoded via `SignedContextOracleV1` (magic 0xff7a1507ba4419ca)
into `RainMetaDocumentV1` are discoverable onchain so callers should not assume
confidentiality of the URL; also suggest optional authentication approaches
(e.g., bearer tokens, client TLS certs, or signature verification of
`SignedContextV1` responses) and indicate that callers must validate TLS and
signature/auth metadata when retrieving `SignedContextV1`.
- Around line 287-289: Update the wording in the documentation fragment that
describes oracle metadata: change “onchain” to “on-chain” and “webapp” to “web
app” to match standard terminology; locate the text mentioning `oracle-url`,
`SignedContextV1`, `SignedContextOracleV1`, and `RainMetaDocumentV1` (including
the magic `0xff7a1507ba4419ca`) and apply the two spelling/wording fixes there.

ob-yaml.md Outdated
Comment on lines +285 to +292
### Oracle URL

Orders that require external data (e.g. price feeds) can specify an `oracle-url`. This URL points to a server that returns `SignedContextV1` data. The signed context is provided by the caller when taking or clearing the order — the order's rainlang can then read this data from the signed context columns during evaluation.

When `oracle-url` is specified, the tooling encodes a `SignedContextOracleV1` metadata item (magic `0xff7a1507ba4419ca`) into the order's `RainMetaDocumentV1`. This allows the oracle endpoint to be discovered onchain by anyone who needs to take or clear the order (e.g. Raindex bots, the webapp, or other takers).

The oracle server MUST respond to `GET` requests and return a JSON object matching the `SignedContextV1` struct:

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Clarify transport/security expectations for oracle-url.

Consider stating whether the URL must be HTTPS (or otherwise authenticated) to avoid leaking endpoint access patterns or enabling downgrade/mitm risks.

🧰 Tools
🪛 LanguageTool

[grammar] ~289-~289: Ensure spelling is correct
Context: ...ws the oracle endpoint to be discovered onchain by anyone who needs to take or clear th...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~289-~289: Ensure spelling is correct
Context: ...clear the order (e.g. Raindex bots, the webapp, or other takers). The oracle server M...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
In `@ob-yaml.md` around lines 285 - 292, Update the Oracle URL documentation to
state transport and security expectations: require HTTPS for the `oracle-url` to
prevent downgrade/MITM, recommend servers use TLS with valid certificates, and
document that endpoints encoded via `SignedContextOracleV1` (magic
0xff7a1507ba4419ca) into `RainMetaDocumentV1` are discoverable onchain so
callers should not assume confidentiality of the URL; also suggest optional
authentication approaches (e.g., bearer tokens, client TLS certs, or signature
verification of `SignedContextV1` responses) and indicate that callers must
validate TLS and signature/auth metadata when retrieving `SignedContextV1`.

ob-yaml.md Outdated
Comment on lines +287 to +289
Orders that require external data (e.g. price feeds) can specify an `oracle-url`. This URL points to a server that returns `SignedContextV1` data. The signed context is provided by the caller when taking or clearing the order — the order's rainlang can then read this data from the signed context columns during evaluation.

When `oracle-url` is specified, the tooling encodes a `SignedContextOracleV1` metadata item (magic `0xff7a1507ba4419ca`) into the order's `RainMetaDocumentV1`. This allows the oracle endpoint to be discovered onchain by anyone who needs to take or clear the order (e.g. Raindex bots, the webapp, or other takers).
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix spelling/wording: “on-chain”, “web app”.

Minor doc polish to match standard terminology.

✏️ Suggested edit
-This allows the oracle endpoint to be discovered onchain by anyone who needs to take or clear the order (e.g. Raindex bots, the webapp, or other takers).
+This allows the oracle endpoint to be discovered on-chain by anyone who needs to take or clear the order (e.g. Raindex bots, the web app, or other takers).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Orders that require external data (e.g. price feeds) can specify an `oracle-url`. This URL points to a server that returns `SignedContextV1` data. The signed context is provided by the caller when taking or clearing the order — the order's rainlang can then read this data from the signed context columns during evaluation.
When `oracle-url` is specified, the tooling encodes a `SignedContextOracleV1` metadata item (magic `0xff7a1507ba4419ca`) into the order's `RainMetaDocumentV1`. This allows the oracle endpoint to be discovered onchain by anyone who needs to take or clear the order (e.g. Raindex bots, the webapp, or other takers).
Orders that require external data (e.g. price feeds) can specify an `oracle-url`. This URL points to a server that returns `SignedContextV1` data. The signed context is provided by the caller when taking or clearing the order — the order's rainlang can then read this data from the signed context columns during evaluation.
When `oracle-url` is specified, the tooling encodes a `SignedContextOracleV1` metadata item (magic `0xff7a1507ba4419ca`) into the order's `RainMetaDocumentV1`. This allows the oracle endpoint to be discovered on-chain by anyone who needs to take or clear the order (e.g. Raindex bots, the web app, or other takers).
🧰 Tools
🪛 LanguageTool

[grammar] ~289-~289: Ensure spelling is correct
Context: ...ws the oracle endpoint to be discovered onchain by anyone who needs to take or clear th...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~289-~289: Ensure spelling is correct
Context: ...clear the order (e.g. Raindex bots, the webapp, or other takers). The oracle server M...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
In `@ob-yaml.md` around lines 287 - 289, Update the wording in the documentation
fragment that describes oracle metadata: change “onchain” to “on-chain” and
“webapp” to “web app” to match standard terminology; locate the text mentioning
`oracle-url`, `SignedContextV1`, `SignedContextOracleV1`, and
`RainMetaDocumentV1` (including the magic `0xff7a1507ba4419ca`) and apply the
two spelling/wording fixes there.

hardyjosh pushed a commit to rainlanguage/rain.orderbook that referenced this pull request Feb 17, 2026
Adds optional oracle-url field to OrderCfg, parsed from the YAML front
matter orders section. When present, this URL identifies a signed context
oracle server for the order.

Changes:
- Add oracle_url: Option<String> to OrderCfg struct
- Parse oracle-url via optional_string in YAML parsing
- Add oracle-url to ALLOWED_ORDER_KEYS
- Update Default and PartialEq impls
- Add test for oracle-url parsing (present + absent)

Spec: rainlanguage/specs#45
Chained on: #2459 (Phase 4)
hardyjosh pushed a commit to rainlanguage/rain.orderbook that referenced this pull request Feb 22, 2026
Adds optional oracle-url field to OrderCfg, parsed from the YAML front
matter orders section. When present, this URL identifies a signed context
oracle server for the order.

Changes:
- Add oracle_url: Option<String> to OrderCfg struct
- Parse oracle-url via optional_string in YAML parsing
- Add oracle-url to ALLOWED_ORDER_KEYS
- Update Default and PartialEq impls
- Add test for oracle-url parsing (present + absent)

Spec: rainlanguage/specs#45
Chained on: #2459 (Phase 4)
Adds a dedicated spec (signed-context-oracle.md) defining the full protocol
for signed context oracle servers compatible with Rain orderbook:
- POST endpoint with ABI-encoded request body
- (OrderV4, uint256 inputIOIndex, uint256 outputIOIndex, address counterparty)
- SignedContextV1 JSON response format
- EIP-191 signing requirements
- Context layout conventions (Rain DecimalFloat)
- Price direction, expiry, security considerations

Updates ob-yaml.md oracle-url section to reference the standalone spec
instead of inlining protocol details. Also fixes:
- GET → POST (matches implementation)
- SignedContextOracleV1 → RaindexSignedContextOracleV1 (matches rename)
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
ob-yaml.md (1)

289-289: ⚠️ Potential issue | 🟡 Minor

webappweb app.

✏️ Suggested fix
-This allows the oracle endpoint to be discovered on-chain by anyone who needs to take or clear the order (e.g. Raindex bots, the webapp, or other takers).
+This allows the oracle endpoint to be discovered on-chain by anyone who needs to take or clear the order (e.g. Raindex bots, the web app, or other takers).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ob-yaml.md` at line 289, The phrase "webapp" should be changed to "web app"
in the sentence describing discovery of the oracle endpoint; update the text
that mentions `oracle-url` and
`RaindexSignedContextOracleV1`/`RainMetaDocumentV1` so it reads "web app"
instead of "webapp" (locate the sentence referencing `oracle-url`,
`RaindexSignedContextOracleV1`, and `RainMetaDocumentV1` and replace the single
word).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@signed-context-oracle.md`:
- Around line 171-177: Add a security note explaining cross-order replay risk
and how to mitigate it: state that signed contexts (context[]) are not
cryptographically bound to a specific order and therefore a valid signed context
can be reused with a different order in takeOrders4(); recommend adding an
explicit binding such as including keccak256(order hash) or the ABI-encoded
OrderV4 bytes32 in the context array and checking that value inside the Rainlang
expression, and mention this as an alternative to relying solely on short
expiry.
- Around line 9-15: The Markdown fenced diagram in signed-context-oracle.md
lacks a language identifier and triggers MD040; update the opening fence from
``` to ```text for the ASCII diagram block so the fence becomes ```text (keep
the closing ``` unchanged) to silence the lint rule and preserve the diagram
content.

---

Duplicate comments:
In `@ob-yaml.md`:
- Line 289: The phrase "webapp" should be changed to "web app" in the sentence
describing discovery of the oracle endpoint; update the text that mentions
`oracle-url` and `RaindexSignedContextOracleV1`/`RainMetaDocumentV1` so it reads
"web app" instead of "webapp" (locate the sentence referencing `oracle-url`,
`RaindexSignedContextOracleV1`, and `RainMetaDocumentV1` and replace the single
word).

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 825a43f and eb41418.

📒 Files selected for processing (2)
  • ob-yaml.md
  • signed-context-oracle.md

Comment on lines +9 to +15
```
External Data Source → Oracle Server → SignedContextV1 JSON
Client (bot/webapp) → POST request → receives signed context
Orderbook Contract → verifies EIP-191 signature → Rainlang evaluation
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Add a language identifier to the ASCII diagram fence to silence MD040.

✏️ Suggested fix
-```
+```text
 External Data Source → Oracle Server → SignedContextV1 JSON
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@signed-context-oracle.md` around lines 9 - 15, The Markdown fenced diagram in
signed-context-oracle.md lacks a language identifier and triggers MD040; update
the opening fence from ``` to ```text for the ASCII diagram block so the fence
becomes ```text (keep the closing ``` unchanged) to silence the lint rule and
preserve the diagram content.

Comment on lines +171 to +177
## Security Considerations

- **Signer trust:** The Rainlang expression is responsible for checking the signer address. An oracle server's signer address should be published and verified out-of-band.
- **Expiry:** Always check expiry on-chain. Without expiry checks, a stale signed context could be replayed indefinitely.
- **Counterparty:** The counterparty address may be `address(0)` at quote time. Oracle servers SHOULD handle this gracefully (e.g. ignore the counterparty field for price-only oracles).
- **HTTPS:** Oracle URLs SHOULD use HTTPS in production. Tooling MAY reject non-HTTPS URLs.
- **CORS:** Oracle servers SHOULD allow cross-origin requests (permissive CORS) so that browser-based frontends can fetch signed contexts directly.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Security consideration missing: cross-order context replay.

The signed context (e.g., [price, expiry]) commits only to context[] values — it contains no cryptographic binding to a specific order hash, inputIOIndex, or outputIOIndex. A valid signed context obtained for order A could be submitted alongside a different order B's takeOrders4() call, as long as both orders trust the same signer and the context is within its expiry window.

The short-expiry recommendation (line 150) limits the window but doesn't eliminate the risk. Consider adding a bullet such as:

Context binding: Signed contexts are not bound to a specific order. If per-order exclusivity is required, include the keccak256 of the order hash (or the full OrderV4 ABI encoding) as an additional bytes32 in the context array, and check it in the Rainlang expression.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@signed-context-oracle.md` around lines 171 - 177, Add a security note
explaining cross-order replay risk and how to mitigate it: state that signed
contexts (context[]) are not cryptographically bound to a specific order and
therefore a valid signed context can be reused with a different order in
takeOrders4(); recommend adding an explicit binding such as including
keccak256(order hash) or the ABI-encoded OrderV4 bytes32 in the context array
and checking that value inside the Rainlang expression, and mention this as an
alternative to relying solely on short expiry.

- Add motivation: why pull oracles, separation of placer and solver/taker
- Remove implementation-specific SHOULDs (expiry, price direction, counterparty handling)
- Clarify security model: order owner bears the risk, chooses their protections
- Rain DecimalFloat encoding is a SHOULD for numeric context values
- Onchain discovery via metadata is a MUST (core to the spec)
- Fix on-chain → onchain
- Move expiry, price direction, counterparty notes to reference implementation
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (3)
signed-context-oracle.md (2)

13-15: ⚠️ Potential issue | 🟠 Major

HTTPS not required — the protocol spec should mandate it.

The endpoint section specifies only that the oracle server "MUST expose a POST endpoint" at the oracle-url, but imposes no transport security requirement. A plain-HTTP oracle-url exposes the full ABI-encoded OrderV4 (including bytecode, vault IDs, owner address) and the counterparty address to passive observers, and allows a network-level MITM to substitute the signed context — defeating the trust assumptions described in the Security Model section.

Given that the signed context is trusted by the contract as long as the signature validates (line 122), a MITM returning a valid but adversarial signed context (if the signer key is shared or otherwise obtainable) could manipulate order evaluation.

Consider adding to the Endpoint section:

 The oracle server MUST expose a `POST` endpoint. The URL of this endpoint is the `oracle-url` specified in the order configuration (see [ob-yaml spec](./ob-yaml.md)).
+
+The `oracle-url` MUST use the `https` scheme. Clients MUST reject oracle URLs with non-HTTPS schemes before sending the request. Oracle servers MUST present a valid TLS certificate.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@signed-context-oracle.md` around lines 13 - 15, The spec currently allows an
oracle `POST` endpoint at `oracle-url` without requiring transport security;
update the Endpoint section to mandate HTTPS/TLS (e.g., require `https://`
scheme or equivalent TLS protection) for the `oracle-url` so the full
ABI-encoded `OrderV4`, `bytecode`, `vault IDs`, `owner` and `counterparty` are
protected in transit and to prevent MITM substitution of the `signed context`
that the contract trusts; reference the `oracle-url`, the `POST` endpoint, and
the `signed context`/`OrderV4` in the updated text and note that plain HTTP is
disallowed.

112-122: ⚠️ Potential issue | 🟠 Major

Cross-order context replay not addressed — existing unresolved concern.

The Security Model does not mention that signed contexts are not bound to a specific order. A valid (signer, context[], signature) tuple obtained for order A can be replayed against order B during the same expiry window, provided both orders trust the same signer address. The three bullet points under the order owner's responsibilities mention "expiry checks" and "price bounds" but say nothing about per-order binding.

Consider adding a bullet:

 - Include any onchain protections they want in their Rainlang expression (e.g. expiry checks, zero ratio guards, price bounds, or any other validation)
+- Understand that signed contexts are not cryptographically bound to a specific order. If per-order exclusivity is required, include a commitment to the order hash (e.g. `keccak256(abi.encode(order))` cast to `bytes32`) as an element in `context[]` and assert it in the Rainlang expression.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@signed-context-oracle.md` around lines 112 - 122, The Security Model must
call out that signed contexts (the (signer, context[], signature) tuple) are not
bound to a specific order and therefore can be replayed across orders sharing
the same signer; update the responsibilities to add a bullet instructing order
owners to enforce per-order binding (e.g., include the order ID/order hash or
unique order-specific nonce inside the signed context or to verify the order
identifier inside their Rainlang expression) and to always validate that the
signed context’s embedded order identifier matches the on-chain order before
using the context.
ob-yaml.md (1)

285-291: ⚠️ Potential issue | 🟠 Major

Transport security for oracle-url still unspecified — consider addressing in the Signed Context Oracle spec.

Neither ob-yaml.md nor the linked signed-context-oracle.md explicitly requires or recommends HTTPS for the oracle-url value. A plain-HTTP oracle-url would expose the ABI-encoded order struct (including counterparty and vault indices) in transit and enable MITM substitution of the signed context. The security model in signed-context-oracle.md (lines 112–122) is the right place to mandate or STRONGLY RECOMMEND HTTPS (and valid TLS certificates).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ob-yaml.md` around lines 285 - 291, Update the Signed Context Oracle spec to
explicitly require or strongly recommend TLS (HTTPS) and valid certificate
verification for any oracle-url, and add a short note in ob-yaml.md alongside
the `oracle-url` / `RaindexSignedContextOracleV1` description referencing that
transport must use HTTPS with certificate validation to prevent MITM and
exposure of ABI-encoded order data; mention acceptable exceptions (if any) and
point readers to the exact section in signed-context-oracle.md for detailed
transport and certificate requirements.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@signed-context-oracle.md`:
- Around line 96-102: The spec currently instructs signing the raw prefix+hash
which omits the additional keccak256 used by EIP-191; update the instructions
around steps 2–3 to explicitly compute the EIP-191 message hash (e.g., call out
toEthSignedMessageHash semantics) by taking final = keccak256("\x19Ethereum
Signed Message:\n32" || keccak256(abi.encodePacked(...))) and then sign(final)
so signatures will match on-chain verification (LibContext.build / ECDSA.recover
using toEthSignedMessageHash).
- Around line 85-92: Update the "Error (4xx/5xx)" response block in
signed-context-oracle.md to explicitly include the Content-Type header (e.g.,
Content-Type: application/json) for error responses so clients can reliably
parse the body; modify the Error (4xx/5xx) section to show the header alongside
the JSON body example and ensure the documentation mirrors the success (200)
response format.

---

Duplicate comments:
In `@ob-yaml.md`:
- Around line 285-291: Update the Signed Context Oracle spec to explicitly
require or strongly recommend TLS (HTTPS) and valid certificate verification for
any oracle-url, and add a short note in ob-yaml.md alongside the `oracle-url` /
`RaindexSignedContextOracleV1` description referencing that transport must use
HTTPS with certificate validation to prevent MITM and exposure of ABI-encoded
order data; mention acceptable exceptions (if any) and point readers to the
exact section in signed-context-oracle.md for detailed transport and certificate
requirements.

In `@signed-context-oracle.md`:
- Around line 13-15: The spec currently allows an oracle `POST` endpoint at
`oracle-url` without requiring transport security; update the Endpoint section
to mandate HTTPS/TLS (e.g., require `https://` scheme or equivalent TLS
protection) for the `oracle-url` so the full ABI-encoded `OrderV4`, `bytecode`,
`vault IDs`, `owner` and `counterparty` are protected in transit and to prevent
MITM substitution of the `signed context` that the contract trusts; reference
the `oracle-url`, the `POST` endpoint, and the `signed context`/`OrderV4` in the
updated text and note that plain HTTP is disallowed.
- Around line 112-122: The Security Model must call out that signed contexts
(the (signer, context[], signature) tuple) are not bound to a specific order and
therefore can be replayed across orders sharing the same signer; update the
responsibilities to add a bullet instructing order owners to enforce per-order
binding (e.g., include the order ID/order hash or unique order-specific nonce
inside the signed context or to verify the order identifier inside their
Rainlang expression) and to always validate that the signed context’s embedded
order identifier matches the on-chain order before using the context.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eb41418 and 117bbf3.

📒 Files selected for processing (2)
  • ob-yaml.md
  • signed-context-oracle.md

- Break signing into 4 explicit steps so implementors don't miss the
  outer keccak256 from toEthSignedMessageHash
- Note that personal_sign/sign_message handles it automatically
- Add Content-Type: application/json to error response section
@hardyjosh hardyjosh self-assigned this Feb 23, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
signed-context-oracle.md (1)

117-128: Cross-order context replay risk is still unaddressed.

The signed context commits only to context[] values with no binding to a specific order hash, inputIOIndex, or outputIOIndex. A valid signed context obtained for order A can be replayed against order B in a takeOrders4() call if both orders trust the same signer and the context is within its expiry window. The short-expiry recommendation (line 124) limits the window but does not eliminate the risk. Consider adding a note such as:

Context binding: If per-order exclusivity is required, include keccak256 of the order hash as an additional bytes32 in the context array and verify it in the Rainlang expression.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@signed-context-oracle.md` around lines 117 - 128, Signed context isn't bound
to a specific order or IO indices, so a valid signed context can be replayed
from order A against order B in takeOrders4() when the same signer is trusted;
fix by documenting a recommended mitigation: bind the context to the order by
adding keccak256(orderHash) (and optionally keccak256(orderHash, inputIOIndex,
outputIOIndex)) as an extra bytes32 entry in the context[] and require the
Rainlang expression to verify that bytes32 is present and matches the expected
keccak256, so replayed contexts are invalid for other orders or IO indices.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@signed-context-oracle.md`:
- Around line 13-15: The spec currently leaves transport security for the
oracle-url unspecified; update the document to require TLS by mandating that the
oracle POST endpoint (the oracle-url) use HTTPS (require the https:// scheme)
and that clients and servers validate certificates (recommend use of CA-signed
certs and modern TLS versions), and add a MUST/SHOULD statement referencing the
POST endpoint, OrderV4, and counterparty to ensure request confidentiality
(e.g., "oracle-url MUST be an https:// URL and oracle servers MUST support TLS
with certificate validation"); also note that implementations SHOULD enforce
secure defaults (no plaintext HTTP fallback) and consider HSTS and recommended
cipher suites.
- Around line 117-128: Update the Security Model text to explicitly require that
Rainlang expressions validate the declared signer: when using SignedContextV1
with takeOrders4(), the expression must check that ECDSA.recover(context_hash,
signature) == signer and that signer matches the order owner's intended oracle
address (or a value derived from it); reference the
SignedContextV1/takeOrders4() flow and the signer/context_hash/signature symbols
so the guidance clearly instructs order owners to add an explicit signer-address
check in their Rainlang expression.

---

Duplicate comments:
In `@signed-context-oracle.md`:
- Around line 117-128: Signed context isn't bound to a specific order or IO
indices, so a valid signed context can be replayed from order A against order B
in takeOrders4() when the same signer is trusted; fix by documenting a
recommended mitigation: bind the context to the order by adding
keccak256(orderHash) (and optionally keccak256(orderHash, inputIOIndex,
outputIOIndex)) as an extra bytes32 entry in the context[] and require the
Rainlang expression to verify that bytes32 is present and matches the expected
keccak256, so replayed contexts are invalid for other orders or IO indices.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 117bbf3 and 09b6b76.

📒 Files selected for processing (1)
  • signed-context-oracle.md

Comment on lines +13 to +15
The oracle server MUST expose a `POST` endpoint. The URL of this endpoint is the `oracle-url` specified in the order configuration (see [ob-yaml spec](./ob-yaml.md)).

There is no `GET` fallback. The request body is always required.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Transport security for the oracle URL is unspecified — recommend mandating HTTPS.

Every request includes the full OrderV4 struct and the counterparty address. Transmitting these over plaintext HTTP leaks pre-confirmation execution intent (taker identity, which order is being taken, timing), which is actionable information for front-running or taker-suppression even though the same data eventually appears on-chain. The signature protects response integrity but not request confidentiality.

The spec should add a SHOULD/MUST constraint:

📝 Proposed addition
 The oracle server MUST expose a `POST` endpoint. The URL of this endpoint is the `oracle-url`
 specified in the order configuration (see [ob-yaml spec](./ob-yaml.md)).

+The `oracle-url` MUST use the `https://` scheme. HTTP endpoints MUST NOT be used, as the
+request body contains sensitive execution intent (taker address, full order struct) that
+would be exposed in plaintext to network observers.
+
 There is no `GET` fallback. The request body is always required.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
The oracle server MUST expose a `POST` endpoint. The URL of this endpoint is the `oracle-url` specified in the order configuration (see [ob-yaml spec](./ob-yaml.md)).
There is no `GET` fallback. The request body is always required.
The oracle server MUST expose a `POST` endpoint. The URL of this endpoint is the `oracle-url` specified in the order configuration (see [ob-yaml spec](./ob-yaml.md)).
The `oracle-url` MUST use the `https://` scheme. HTTP endpoints MUST NOT be used, as the request body contains sensitive execution intent (taker address, full order struct) that would be exposed in plaintext to network observers.
There is no `GET` fallback. The request body is always required.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@signed-context-oracle.md` around lines 13 - 15, The spec currently leaves
transport security for the oracle-url unspecified; update the document to
require TLS by mandating that the oracle POST endpoint (the oracle-url) use
HTTPS (require the https:// scheme) and that clients and servers validate
certificates (recommend use of CA-signed certs and modern TLS versions), and add
a MUST/SHOULD statement referencing the POST endpoint, OrderV4, and counterparty
to ensure request confidentiality (e.g., "oracle-url MUST be an https:// URL and
oracle servers MUST support TLS with certificate validation"); also note that
implementations SHOULD enforce secure defaults (no plaintext HTTP fallback) and
consider HSTS and recommended cipher suites.

Comment on lines +117 to +128
## Security Model

The order owner is the party who stands to lose funds if the oracle misbehaves — they are trusting the oracle server (identified by its signer address) with control over the data their order uses to calculate ratios, maximums, and any other logic.

It is the order owner's responsibility to:

- Choose an oracle and signer they trust
- Include any onchain protections they want in their Rainlang expression (e.g. expiry checks, zero ratio guards, price bounds, or any other validation)
- Understand that the oracle server has full knowledge of the order struct, IO pair, and counterparty for every request

The contract enforces only that the signature is valid for the declared signer address. All other validation is up to the Rainlang expression.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Security model should explicitly require signer-address verification in the Rainlang expression.

The signer field is a runtime input supplied by the taker when constructing SignedContextV1 for takeOrders4(). The contract verifies only that ECDSA.recover(context_hash, signature) == signer — it does not check that signer matches any address the order owner intended. Without an explicit signer check in the expression, a taker can generate their own key pair, sign arbitrary context values, set signer to their own address, and the contract will accept it.

Line 127 mentions this indirectly ("All other validation is up to the Rainlang expression"), but an order owner who misses this will deploy a fully open oracle socket. Add an explicit bullet to the responsibility list:

📝 Proposed addition
 It is the order owner's responsibility to:

 - Choose an oracle and signer they trust
+- **Verify the signer address in the Rainlang expression.** The contract does not enforce
+  which signer is used; it only checks that the signature is valid for the declared signer.
+  The expression MUST compare the runtime signer against a trusted address hardcoded at
+  order-placement time, otherwise any party can inject arbitrary context.
 - Include any onchain protections they want in their Rainlang expression (e.g. expiry checks,
   zero ratio guards, price bounds, or any other validation)
🧰 Tools
🪛 LanguageTool

[grammar] ~124-~124: Ensure spelling is correct
Context: ...cle and signer they trust - Include any onchain protections they want in their Rainlang...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~125-~125: Ensure spelling is correct
Context: ... server has full knowledge of the order struct, IO pair, and counterparty for every re...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@signed-context-oracle.md` around lines 117 - 128, Update the Security Model
text to explicitly require that Rainlang expressions validate the declared
signer: when using SignedContextV1 with takeOrders4(), the expression must check
that ECDSA.recover(context_hash, signature) == signer and that signer matches
the order owner's intended oracle address (or a value derived from it);
reference the SignedContextV1/takeOrders4() flow and the
signer/context_hash/signature symbols so the guidance clearly instructs order
owners to add an explicit signer-address check in their Rainlang expression.

- Change request from single tuple to array of tuples
- Change response from single JSON object to array
- Array length must match between request and response
- Each signature applies to its corresponding context array
hardyjosh pushed a commit to rainlanguage/rain.orderbook that referenced this pull request Feb 23, 2026
Adds optional oracle-url field to OrderCfg, parsed from the YAML front
matter orders section. When present, this URL identifies a signed context
oracle server for the order.

Changes:
- Add oracle_url: Option<String> to OrderCfg struct
- Parse oracle-url via optional_string in YAML parsing
- Add oracle-url to ALLOWED_ORDER_KEYS
- Update Default and PartialEq impls
- Add test for oracle-url parsing (present + absent)

Spec: rainlanguage/specs#45
Chained on: #2459 (Phase 4)
hardyjosh pushed a commit to rainlanguage/rain.orderbook that referenced this pull request Feb 24, 2026
Adds optional oracle-url field to OrderCfg, parsed from the YAML front
matter orders section. When present, this URL identifies a signed context
oracle server for the order.

Changes:
- Add oracle_url: Option<String> to OrderCfg struct
- Parse oracle-url via optional_string in YAML parsing
- Add oracle-url to ALLOWED_ORDER_KEYS
- Update Default and PartialEq impls
- Add test for oracle-url parsing (present + absent)

Spec: rainlanguage/specs#45
Chained on: #2459 (Phase 4)
hardyjosh added a commit to rainlanguage/rain.orderbook that referenced this pull request Mar 6, 2026
* fix: prettier formatting

* feat: parse oracle-url from YAML order config (Phase 6)

Adds optional oracle-url field to OrderCfg, parsed from the YAML front
matter orders section. When present, this URL identifies a signed context
oracle server for the order.

Changes:
- Add oracle_url: Option<String> to OrderCfg struct
- Parse oracle-url via optional_string in YAML parsing
- Add oracle-url to ALLOWED_ORDER_KEYS
- Update Default and PartialEq impls
- Add test for oracle-url parsing (present + absent)

Spec: rainlanguage/specs#45
Chained on: #2459 (Phase 4)

* feat: encode oracle-url into order metadata (Phase 7)

When an order has oracle_url set in its config, new_from_deployment now
creates a SignedContextOracleV1 meta item and includes it in the order's
additional_meta. This means orders deployed with oracle-url in their YAML
will have the oracle endpoint encoded in their onchain RainMetaDocumentV1,
making it discoverable by takers and indexers (Phase 2 reads it back).

Changes:
- Import SignedContextOracleV1 in add_order.rs
- In new_from_deployment: parse oracle_url, create meta item, append to
  additional_meta

* propagate RaindexSignedContextOracleV1 rename to add_order.rs

* fix: cargo fmt formatting

---------

Co-authored-by: Josh Hardy <josh@rainlang.xyz>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant