Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,20 @@ OpenGradient operates two networks:

For current network RPC endpoints, contract addresses, and deployment information, refer to the [Network Deployment Documentation](https://docs.opengradient.ai/learn/network/deployment.html).

## Trust Model

OpenGradient's verifiable inference relies on three distinct layers. Understanding which layer enforces what makes it easier to reason about what an SDK response does and does not guarantee.

1. **TEE attestation (network-side, at registration).** Each TEE proves its identity and code measurement (PCR hash) to the OpenGradient network when it registers in the on-chain `TEERegistry` contract. The network verifies the attestation and stores the TEE's public key, PCR hash, and TLS certificate on-chain. SDK clients do not re-run attestation themselves.

2. **TLS certificate pinning (SDK-side, at request time).** When the SDK resolves a TEE through `RegistryTEEConnection` (the production path), it reads the registered TLS certificate directly from the registry and pins it as the *only* trust anchor for the connection (`CERT_REQUIRED`, no system-CA fallback). A successful response is therefore, by TLS construction, from a TEE the network has already attested. This is the live trust binding for SDK responses.

3. **Signature verification (settlement-side, on-chain).** The `tee_signature` and `tee_timestamp` returned with each response are durable proof material. Signature verification happens during on-chain settlement, not in the SDK at return time. These fields are also useful for offline / auditor verification when a response leaves the original TLS session.

> **Note:** The SDK does **not** verify `tee_signature` client-side at return time. A non-erroring response means the TLS-pinned channel was honored; signature checking lives at the settlement layer. If you archive a response and want to re-verify it offline, use the registry's stored public key for that TEE.
>
> The `StaticTEEConnection` mode (used for self-hosted dev with `verify=False`) bypasses both the registry and TLS pinning, and is **not a production trust path**.

## Getting Started

### Prerequisites
Expand Down Expand Up @@ -142,7 +156,7 @@ See [Payment Settlement](#payment-settlement) for details on settlement modes.

### TEE-Secured LLM Chat

OpenGradient provides secure, verifiable inference through Trusted Execution Environments. All supported models include cryptographic attestation verified by the OpenGradient network. LLM methods are async:
OpenGradient provides secure, verifiable inference through Trusted Execution Environments. All supported models run in TEEs whose attestation is verified by the OpenGradient network at registration; the SDK binds each request to an attested TEE via registry-pinned TLS, and signed proof material is verified at on-chain settlement (see [Trust Model](#trust-model)). LLM methods are async:
```python
completion = await llm.chat(
model=og.TEE_LLM.GPT_5,
Expand Down
14 changes: 12 additions & 2 deletions src/opengradient/client/tee_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,18 @@ async def close(self) -> None: ...
class StaticTEEConnection:
"""TEE connection with a hardcoded endpoint URL.

No registry lookup, no background refresh. TLS certificate verification
is disabled because self-hosted TEE servers typically use self-signed certs.
Intended for self-hosted development only. No registry lookup, no
background refresh, and TLS certificate verification is disabled
(``verify=False``) because self-hosted TEE servers typically use
self-signed certs.

Warning:
This is **not a production trust path**. Because TLS is unverified,
the connection is not bound to a network-attested TEE: there is no
registry cert pinning and no PCR-attested identity. Responses
received over this connection should not be treated as TEE-verified.
For production use, resolve TEEs via ``RegistryTEEConnection``,
which pins the on-chain registry's TLS certificate.

Args:
x402_client: Configured x402 payment client for creating HTTP clients.
Expand Down
34 changes: 26 additions & 8 deletions src/opengradient/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,10 @@ class StreamChunk:
model: Model identifier
usage: Token usage information (only in final chunk)
is_final: Whether this is the final chunk (before [DONE])
tee_signature: RSA-PSS signature over the response, present on the final chunk
tee_signature: RSA-PSS signature over the response, present on the final chunk.
Forwarded as-is; verified at on-chain settlement, not by the SDK. Live
trust comes from the registry-pinned TLS channel — see
``TextGenerationOutput`` for the trust model.
tee_timestamp: ISO timestamp from the TEE at signing time, present on the final chunk
tee_id: On-chain TEE registry ID of the enclave that served this request (final chunk only)
tee_endpoint: Endpoint URL of the TEE that served this request (final chunk only)
Expand Down Expand Up @@ -403,9 +406,21 @@ class TextGenerationOutput:
**completion** requests it is in ``completion_output``. Only the
field that matches the request type will be populated.

Every response includes a ``tee_signature`` and ``tee_timestamp``
that can be used to cryptographically verify the inference was
performed inside a TEE enclave.
Trust model:
Live trust in the response comes from the **TLS channel** the SDK
used to obtain it: when the TEE is resolved via the on-chain
registry, the SDK pins the registry-attested TLS certificate, so
a successful response is, by construction, from a network-attested
TEE enclave. See ``opengradient.client.tee_registry`` for the
pinning logic.

``tee_signature`` and ``tee_timestamp`` are durable proof material
intended for **on-chain settlement verification** and offline /
auditor use (e.g. when a response is archived and re-checked
outside the original TLS session). The SDK does not verify the
signature at return time, and a non-erroring response does not
imply client-side signature verification has occurred — only that
the TLS-pinned channel was honored.

Attributes:
data_settlement_transaction_hash: Blockchain transaction hash for
Expand All @@ -422,10 +437,12 @@ class TextGenerationOutput:
optionally ``tool_calls``.
completion_output: Raw text returned by a completion request.
payment_hash: Payment hash for the x402 transaction.
tee_signature: RSA-PSS signature over the response produced
by the TEE enclave.
tee_signature: RSA-PSS signature over the response produced by
the TEE enclave. Forwarded as-is from the server; verified at
settlement on-chain, not by the SDK at return time. See the
class-level "Trust model" note above.
tee_timestamp: ISO-8601 timestamp from the TEE at signing
time.
time. Forwarded as-is alongside ``tee_signature``.
"""

data_settlement_transaction_hash: Optional[str] = None
Expand All @@ -450,7 +467,8 @@ class TextGenerationOutput:
"""Payment hash for the x402 transaction."""

tee_signature: Optional[str] = None
"""RSA-PSS signature over the response produced by the TEE enclave."""
"""RSA-PSS signature over the response produced by the TEE enclave.
Forwarded as-is; verified at on-chain settlement, not at SDK return time."""

tee_timestamp: Optional[str] = None
"""ISO-8601 timestamp from the TEE at signing time."""
Expand Down
Loading