From 4ab7957a55599832b7c52a8c6d4e640b18beeb3f Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:00:36 +0300 Subject: [PATCH 01/58] [DOCS] deep-dive/teecryptor: new page for the TEE decryption service, replaces threshold-network content --- deep-dive/cofhe-components/teecryptor.mdx | 94 +++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 deep-dive/cofhe-components/teecryptor.mdx diff --git a/deep-dive/cofhe-components/teecryptor.mdx b/deep-dive/cofhe-components/teecryptor.mdx new file mode 100644 index 0000000..e36dfa9 --- /dev/null +++ b/deep-dive/cofhe-components/teecryptor.mdx @@ -0,0 +1,94 @@ +--- +title: Teecryptor +description: "Offchain decryption service that decrypts CoFHE ciphertexts inside a hardware-attested Trusted Execution Environment (TEE)" +--- + +| Aspect | Description | +| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **Type** | Offchain service running inside a hardware-attested Trusted Execution Environment (TEE). | +| **Function** | Process decryption requests from the [Client SDK](/client-sdk/introduction/overview). | +| **Responsibilities** | β€’ Authorizes each request against the onchain ACL
β€’ Verifies the ciphertext against its onchain commitment
β€’ Decrypts inside the enclave
β€’ Signs (or seals) the result for delivery | + +Teecryptor is the component that decrypts CoFHE ciphertexts. It holds the FHE secret key, but only inside a TEE: an isolated, hardware-encrypted execution environment (Intel TDX) whose exact code image is proven by remote attestation. The trust model is deliberate and worth stating plainly. Instead of splitting the decryption computation across independent parties, Teecryptor relies on hardware attestation to guarantee that only one specific, reviewable program can ever touch the key. A [Threshold Network](/deep-dive/research/future-plans) that decrypts through multi-party computation is the planned next step and will eventually replace Teecryptor. + +## How a decrypt request is processed + +Every `decrypt` and `sealoutput` request carries a ciphertext handle, a host chain id, and optionally a [permit](/client-sdk/guides/permits). Teecryptor then runs a fixed pipeline: + + + + +Teecryptor checks the handle against the onchain ACL through the [TaskManager](/deep-dive/cofhe-components/task-manager) on the requested host chain. With a permit, the contract verifies the permit's EIP-712 signature and calls `isAllowedWithPermission`. Without a permit, the handle must have been marked publicly decryptable, checked via `isPubliclyAllowed`. Both paths fail closed: no onchain allowance, no decryption. + + + +Concurrently with authorization, Teecryptor confirms that the [FHE Engine](/deep-dive/cofhe-components/fheos-server) posted a commitment for this handle in the [CommitmentRegistry](/deep-dive/cofhe-components/commitment-registry). Commitments are write-once, so a verified result is cached permanently. + + + +The ciphertext is fetched from the ciphertext store exactly as the FHE Engine stored it, and its bytes must hash to the onchain commitment. A missing commitment or mismatched bytes rejects the request. This validates the ciphertext against the onchain commitment before anything is decrypted: Teecryptor only ever decrypts bytes the coprocessor committed to publicly. + + + +The stored ciphertext is decrypted directly with the FHE secret key, inside the enclave, without re-expanding it first. Decrypting the committed bytes as-is keeps the integrity check meaningful, because the exact bytes that were hashed are the bytes that get decrypted. + + + +For `decrypt` (the `decryptForTx` path), the plaintext is signed with an ECDSA key that never leaves the enclave, producing a result any contract can verify onchain. For `sealoutput` (the `decryptForView` path), the plaintext is instead encrypted to the permit's sealing key using NaCl `crypto_box` (X25519 with XSalsa20-Poly1305). Only the permit holder can read it, and the SDK unseals it locally. + + + + + +A handle whose ciphertext or commitment has not landed yet is not an error. Teecryptor answers with a retryable status and the SDK re-submits automatically, roughly once per second within a multi-minute budget. + + +```mermaid +sequenceDiagram + participant SDK as Client SDK + participant Teecryptor + participant TaskManager as TaskManager (host chain) + participant Registry as CommitmentRegistry + participant Store as Ciphertext store + + SDK->>Teecryptor: decrypt / sealoutput (handle, chain id, permit?) + par Authorization + Teecryptor->>TaskManager: isAllowedWithPermission / isPubliclyAllowed + TaskManager-->>Teecryptor: allowed + and Commitment lookup + Teecryptor->>Registry: commitment for handle + Registry-->>Teecryptor: expected hash + end + Teecryptor->>Store: fetch stored ciphertext + Store-->>Teecryptor: ciphertext bytes + Teecryptor->>Teecryptor: verify bytes hash to commitment + Teecryptor->>Teecryptor: decrypt in enclave, sign (or seal) result + Teecryptor-->>SDK: plaintext + signature (or sealed output) +``` + +## Attestation + +Remote attestation is what turns "trust the operator" into "verify the code". Before Teecryptor can obtain any key material, the TEE hardware produces an attestation of the exact code image it is running. Each key-share custodian independently checks that attestation and releases its share only to the approved image digest. The guarantee this yields: the FHE key can only be reconstructed by the exact reviewed code, running on genuine TEE hardware. Nothing else, including the infrastructure operator, can obtain the key or observe the enclave's memory, which the hardware keeps encrypted. + +## Key custody + +The FHE secret key is never stored whole. It is split with Shamir secret sharing into six shares held by independent parties, with any three required for reconstruction (3-of-6). At boot, the attested enclave collects shares from the custodians, reconstructs the key in memory, and zeroizes the transient share material. The reconstructed key exists only inside the enclave for the lifetime of the process. It is never persisted. The result-signing key travels inside the same split secret, so it too can only materialize inside the attested enclave. + +## Result signing + +Every `decrypt` result is signed so the TaskManager can verify it onchain. Teecryptor builds a fixed 76-byte message and signs its keccak256 hash with secp256k1: + +| Field | Size | Encoding | +|-------|------|----------| +| `result` | 32 bytes | uint256, big-endian, left-padded with zeros | +| `enc_type` | 4 bytes | i32, big-endian | +| `chain_id` | 8 bytes | u64, big-endian | +| `ct_hash` | 32 bytes | uint256, big-endian | + +This layout matches what the TaskManager reconstructs in `_computeDecryptResultHash`, so `FHE.publishDecryptResult(ctHash, result, signature)` verifies the signature onchain before storing the plaintext. Request the signature with the `X-Signature-V-Format: evm` header (the SDK does this for you) so the recovery id is 27/28 and directly compatible with Solidity's `ecrecover`. + +Teecryptor's signer address is registered onchain as `decryptResultSigner` in the TaskManager. Only results signed by that address are accepted. + +## What comes next + +Teecryptor concentrates key custody at runtime in a single attested machine. The planned Threshold Network removes that concentration by decrypting through multi-party computation, where no party ever holds the full key. See [Future Plans](/deep-dive/research/future-plans). From 21a26fb74ccd9dd40e60f8f4916ecca84ca92464 Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:00:36 +0300 Subject: [PATCH 02/58] [DOCS] deep-dive/decryption-request-flow: rewrite around the SDK-driven decrypt path --- .../data-flows/decryption-request-flow.mdx | 115 +++++++++++------- 1 file changed, 73 insertions(+), 42 deletions(-) diff --git a/deep-dive/data-flows/decryption-request-flow.mdx b/deep-dive/data-flows/decryption-request-flow.mdx index f10bf11..9a5b940 100644 --- a/deep-dive/data-flows/decryption-request-flow.mdx +++ b/deep-dive/data-flows/decryption-request-flow.mdx @@ -1,70 +1,101 @@ --- title: Decryption Request Flow sidebar_position: 3 -description: "Complete flow of a decryption request in the CoFHE ecosystem through smart contracts" +description: "End-to-end path of a decryption: SDK request, TEE decryption, signed result, onchain publication, contract read-back" --- -# Decryption Request Flow +This page follows a plaintext all the way onto the chain: from the SDK's `decryptForTx` call, through [Teecryptor](/deep-dive/cofhe-components/teecryptor), to a signed result the TaskManager verifies and any contract can read. -The process of requesting decryption through Smart Contracts starts the same as every other [FHE Operation Request](/deep-dive/data-flows/fhe-operation-request-flow) πŸ“Œsteps 1-4 - -Here we'll continue from FheOS server handling such request as follows: - -## Flow Diagram - -The following diagram illustrates the complete flow of an FHE Decryption request in the CoFHE ecosystem: + +**Contracts cannot request decryption onchain.** The TaskManager rejects decrypt tasks (`DecryptFunctionNotSupported`), and `FHE.decrypt` no longer exists in the FHE library. Decryption is exclusively SDK-driven. A contract's role is to grant access (`FHE.allow`, `FHE.allowGlobal`, or `TaskManager.allowForDecryption`) and later read the published result. This design keeps decryption off the transaction path. The coprocessor never pushes plaintexts into your contract; anyone holding a valid signature publishes the result, and the contract verifies that signature itself. + - -End-to-end flow of an FHE Decryption request through the CoFHE system components - +There are two SDK entry points: -*Figure 1: End-to-end flow of an FHE Decryption request through the CoFHE system components* +- **`decryptForTx`**: returns the plaintext with a signature you can publish onchain. This page covers it. +- **`decryptForView`**: returns a sealed result only the permit holder can read, for UI display. Covered in the [Offchain Decryption Flow](/deep-dive/data-flows/offchain-decryption-flow). -## Step-by-Step Flow +## Step-by-step flow - -The decryption request follows the same initial steps as a standard FHE operation request: - -1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ -Refer to [FHE Operation Request Flow](/deep-dive/data-flows/fhe-operation-request-flow) for details on steps 1-4, which include: -- Integration with the Client SDK -- Requesting an FHE Operation -- Task Manager Processing -- Slim Listener Processing + +The contract that owns the encrypted value marks the handle decryptable: `FHE.allow(handle, account)` for a specific account, or `FHE.allowGlobal(handle)` when the value may become public. Without an ACL grant, Teecryptor refuses the request. - -The FheOS server handles decryption requests: + +The user calls `decryptForTx` with the ciphertext handle: -1. **Create execution thread** on the fheOS server +```typescript +const { ctHash, decryptedValue, signature } = await client + .decryptForTx(ctHash) + .withPermit() + .execute(); +``` -2. **FheOS server calls the threshold network** with: - - The ciphertext to be decrypted - - Transaction hash from the host chain - - Original operation handle +The request goes to Teecryptor with the handle, the host chain id, and the [permit](/client-sdk/guides/permits). For publicly decryptable handles, use `.withoutPermit()`. - -The Threshold Network performs secure decryption: + +Teecryptor authorizes the request against the onchain ACL, fetches the ciphertext exactly as stored, verifies it against the onchain commitment, and decrypts it inside the attested TEE. If the ciphertext or its commitment has not landed yet (a freshly computed handle), the SDK retries automatically until it is available. + +See the [Teecryptor page](/deep-dive/cofhe-components/teecryptor) for the full pipeline. + -- Verify the host chain requested the desired decryption -- Retrieve the actual ciphertext hash from private storage -- Validate ciphertext hash integrity -- Perform secure decryption + +Teecryptor returns the plaintext together with an ECDSA signature over a fixed 76-byte message (result, encryption type, chain id, ciphertext hash). The signing key lives only inside the enclave, and its address is registered onchain as the TaskManager's `decryptResultSigner`. - -After decryption is complete: 7️⃣ + +Anyone holding the signature submits it in a transaction: + +```solidity +FHE.publishDecryptResult(ctHash, result, signature); +``` -- The Threshold Network returns the plaintext along with an **ECDSA signature** to the client (via the Client SDK) -- The client (or any relayer) calls `FHE.publishDecryptResult(ctHash, result, signature)` or `FHE.verifyDecryptResult(ctHash, result, signature)` on-chain -- The on-chain contract verifies the signature before accepting the result +The TaskManager recomputes the message hash, recovers the signer, and rejects anything not signed by `decryptResultSigner`. On success it stores the plaintext in PlaintextsStorage and emits a `DecryptionResult` event. `publishDecryptResultBatch` amortizes gas across multiple results. -This enables permissionless result delivery β€” anyone holding a valid signature can publish. This is useful for client-driven settlement or relayer patterns. +Publication is permissionless: any relayer with a valid signature can deliver the result. `decryptForTx` itself costs no gas; gas is paid only by this publish transaction. + + +Once published, any contract reads the plaintext: + +```solidity +uint64 value = FHE.getDecryptResult(handle); // reverts if not yet published +(uint64 value, bool ready) = FHE.getDecryptResultSafe(handle); // non-reverting variant +``` + +To check a signature without storing the result, use the `verifyDecryptResult` family on the TaskManager. + + +## Flow diagram + +```mermaid +sequenceDiagram + participant User + participant SDK as Client SDK + participant Teecryptor + participant TaskManager + participant Contract as Your contract + + Contract->>TaskManager: FHE.allow / allowGlobal (grant access) + User->>SDK: decryptForTx(ctHash) + SDK->>Teecryptor: decrypt request (handle, chain id, permit?) + Teecryptor->>TaskManager: ACL check + Teecryptor->>Teecryptor: verify commitment, decrypt in TEE, sign + Teecryptor-->>SDK: plaintext + signature + SDK-->>User: { ctHash, decryptedValue, signature } + User->>TaskManager: FHE.publishDecryptResult(ctHash, result, signature) + TaskManager->>TaskManager: verify signer, store plaintext, emit DecryptionResult + Contract->>TaskManager: FHE.getDecryptResult(handle) + TaskManager-->>Contract: plaintext +``` + +## Future plans + +Decryption is currently performed by Teecryptor inside a hardware-attested TEE. A multi-party Threshold Network is the planned successor; see [Future Plans](/deep-dive/research/future-plans). From 1968319ad53a8823a46f88006143a523f3f8428c Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:03:57 +0300 Subject: [PATCH 03/58] [DOCS] deep-dive/off-chain-decryption-flow: rewrite around Teecryptor and current SDK signatures --- .../data-flows/off-chain-decryption-flow.mdx | 116 +++++++++++------- 1 file changed, 69 insertions(+), 47 deletions(-) diff --git a/deep-dive/data-flows/off-chain-decryption-flow.mdx b/deep-dive/data-flows/off-chain-decryption-flow.mdx index e5c35fe..2a17a95 100644 --- a/deep-dive/data-flows/off-chain-decryption-flow.mdx +++ b/deep-dive/data-flows/off-chain-decryption-flow.mdx @@ -1,33 +1,33 @@ --- -title: Off-Chain Decryption Flow +title: Offchain Decryption Flow sidebar_position: 4 -description: "Complete flow of off-chain decryption using decryptForTx and decryptForView" +description: "How to decrypt CoFHE values with decryptForTx and decryptForView, from ACL grant to plaintext" --- -# Off-Chain Decryption Flow +Decryption in CoFHE is SDK-driven. Contracts cannot request it onchain; instead, your application asks [Teecryptor](/deep-dive/cofhe-components/teecryptor) to decrypt a handle it is allowed to read. There are two methods: -## Overview +- **`decryptForTx`**: returns the plaintext and a Teecryptor signature. Use it when the decrypted value needs to go onchain, via `FHE.publishDecryptResult` or the `verifyDecryptResult` family. +- **`decryptForView`**: returns the plaintext sealed to your permit. Use it for UI display or offchain reads where no onchain proof is needed. -This document lays out the complete flow of off-chain decryption requests. There are two methods for decrypting encrypted data off-chain: - -- **`decryptForTx`** β€” Returns the plaintext value and a Threshold Network signature. Used when the decrypted value needs to be submitted on-chain (e.g., via `FHE.publishDecryptResult` or `FHE.verifyDecryptResult`). -- **`decryptForView`** β€” Returns only the plaintext value. Used for UI display or off-chain reads where no on-chain proof is needed. + +A freshly computed handle may not be decryptable immediately: its ciphertext and commitment land shortly after the transaction. Until then Teecryptor answers with a retryable status and the SDK re-submits automatically. + -## Key Components +## Key components | Component | Description | -| --------------------- | ------------------------------------------------------------------------------------ | -| **CtHash** | A `bytes32` handle representing an encrypted value. Fetched on-chain. | -| **SDK Client** | Client library handling `permits` and the `decryptForTx` / `decryptForView` operations. | -| **Threshold Network** | Decentralized decryption network that handles the requests and produces signatures. | -| **ACL** | On-chain **A**ccess **C**ontrol **L**ist responsible for tracking **CtHash** access. | +| --- | --- | +| **CtHash** | A `bytes32` handle representing an encrypted value, read from the chain. | +| **SDK client** | Client library handling [permits](/client-sdk/guides/permits) and the `decryptForTx` / `decryptForView` operations. | +| **Teecryptor** | Offchain decryption service running in an attested TEE. Verifies access onchain and returns signed or sealed results. | +| **ACL** | Onchain access control list that tracks who may decrypt each handle. | -## decryptForTx Flow +## The `decryptForTx` flow -Use `decryptForTx` when you need to submit the decrypted value on-chain with a proof. +Use `decryptForTx` when you need to submit the decrypted value onchain with a proof. - + Solidity contract: ```solidity @@ -53,7 +53,7 @@ All encrypted types (`euint8`, `euint16`, `euint32`, `euint64`, `euint128`, `ebo - + Call `decryptForTx` on the SDK client. Since `FHE.allowPublic` was used, no permit is needed: ```typescript @@ -73,17 +73,17 @@ const result = await client ``` - + Behind the scenes: -1. The SDK sends the decryption request to the Threshold Network -2. The Threshold Network verifies on-chain that the requester has access to the `CtHash` via the ACL -3. The Threshold Network performs secure decryption -4. The Threshold Network signs the plaintext result and returns both the plaintext and the signature +1. The SDK sends the request to Teecryptor with the handle, the host chain id, and the permit if one was attached. +2. Teecryptor checks the onchain ACL. With a permit it calls `isAllowedWithPermission` for the permit's issuer; without one, the handle must pass `isPubliclyAllowed`. +3. Teecryptor verifies the stored ciphertext against its onchain commitment and decrypts it inside the enclave. +4. Teecryptor signs the plaintext with its onchain-registered key and returns both the plaintext and the signature. - -The SDK returns an object containing the decrypted value and signature. Submit these on-chain: + +The SDK returns an object containing the decrypted value and signature. Submit these onchain: ```typescript // result contains: { ctHash, decryptedValue, signature } @@ -94,7 +94,7 @@ await example.revealCount( ); ``` -The on-chain function verifies the signature using `FHE.publishDecryptResult` or `FHE.verifyDecryptResult`: +The onchain function verifies the signature using `FHE.publishDecryptResult` or `FHE.verifyDecryptResult`: ```solidity function revealCount(uint32 _decrypted, bytes memory _signature) external { @@ -104,14 +104,12 @@ function revealCount(uint32 _decrypted, bytes memory _signature) external { ---- - -## decryptForView Flow +## The `decryptForView` flow -Use `decryptForView` when you only need to display the value in the UI β€” no on-chain transaction is needed. +Use `decryptForView` when you only need to read the value offchain, for example to display it in a UI. No onchain transaction is involved. - + The contract must have granted access to the user via `FHE.allow` or `FHE.allowSender`: ```solidity @@ -135,37 +133,61 @@ const ctHash = await example.getBalance(); ``` - -Call `decryptForView` with a permit (required since this is user-specific data): + +Call `decryptForView` with a permit and the value's FHE type. The type tells the SDK how to decode the result: ```typescript -const result = await client - .decryptForView(ctHash) +const balance = await client + .decryptForView(ctHash, FheTypes.Uint32) .withPermit() .execute(); -console.log(`Balance: ${result.decryptedValue}`); +console.log(`Balance: ${balance}`); ``` + +`execute()` returns the decoded plaintext directly. - + Behind the scenes: -1. The SDK sends the decryption request with the user's permit to the Threshold Network -2. The Threshold Network verifies the permit's signature and checks on-chain that `permit.issuer` has access to the `CtHash` via the ACL -3. The Threshold Network performs secure decryption -4. The plaintext value is returned to the SDK (no signature needed since this is view-only) +1. The SDK sends the request with the user's permit. +2. Teecryptor verifies the permit's EIP-712 signature onchain and checks that the permit's issuer has access to the handle. +3. Teecryptor verifies the ciphertext commitment and decrypts inside the enclave, exactly as in the `decryptForTx` path. +4. Instead of a bare plaintext, Teecryptor returns the result encrypted to the permit's sealing key. The SDK unseals it locally, so the plaintext is never exposed in transit. ---- +## Flow diagram + +```mermaid +sequenceDiagram + participant App as Your app + participant SDK as Client SDK + participant Teecryptor + participant Chain as Host chain + + App->>SDK: decryptForTx / decryptForView (ctHash) + SDK->>Teecryptor: decrypt or sealoutput request (handle, chain id, permit?) + Teecryptor->>Chain: ACL check (isAllowedWithPermission / isPubliclyAllowed) + Teecryptor->>Teecryptor: verify commitment, decrypt in enclave + alt decryptForTx + Teecryptor-->>SDK: plaintext + signature + SDK-->>App: { ctHash, decryptedValue, signature } + App->>Chain: FHE.publishDecryptResult(ctHash, result, signature) + else decryptForView + Teecryptor-->>SDK: result sealed to the permit's sealing key + SDK->>SDK: unseal locally + SDK-->>App: plaintext + end +``` ## Comparison | | `decryptForTx` | `decryptForView` | |---|---|---| -| **Returns** | Plaintext + Threshold Network signature | Plaintext only | -| **Use case** | Submit decrypted value on-chain | Display in UI | -| **Requires permit** | Only if not `allowPublic` | Yes | -| **On-chain verification** | `publishDecryptResult` or `verifyDecryptResult` | Not applicable | -| **Gas cost** | Yes (on-chain tx needed) | None | +| **Returns** | Plaintext + Teecryptor signature | Plaintext (sealed in transit, unsealed by the SDK) | +| **Use case** | Submit the decrypted value onchain | Display in a UI, offchain reads | +| **Requires permit** | Only if the handle is not publicly decryptable | Yes | +| **Onchain verification** | `publishDecryptResult` or `verifyDecryptResult` | Not applicable | +| **Gas cost** | None for the decryption itself; gas only for the publish transaction | None | From 3fceff9d1ae3e873047efbdd199527aa5f9784c7 Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:07:03 +0300 Subject: [PATCH 04/58] [DOCS] deep-dive/overview: rewrite to current topology, replace Architecture.svg with Mermaid --- deep-dive/cofhe-components/overview.mdx | 126 ++++++++++++++---------- 1 file changed, 75 insertions(+), 51 deletions(-) diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index 0d6e878..c8b4fdf 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -1,55 +1,79 @@ --- title: "CoFHE Architecture Overview" -description: "Comprehensive overview of the CoFHE architecture, components, and data flows for privacy-preserving blockchain computations" +description: "How CoFHE's onchain contracts and offchain services fit together to run FHE computations for any EVM chain" --- -# CoFHE Architecture - - -CoFHE Architecture Diagram - - -*Click on the image to view in full size* - -## System Overview - -CoFHE (Co-processor for Fully Homomorphic Encryption) is designed as a modular, layered architecture that enables privacy-preserving computations on blockchain networks. The system combines on-chain smart contracts with off-chain processing capabilities to deliver secure, efficient fully homomorphic encryption operations. - -### Key Components - -#### User-Facing Utilities - -- **Client SDK** (`@cofhe/sdk`): A TypeScript library that provides client-side functionality for encrypting inputs, managing permits, and decrypting outputs. Serves as the primary interface between applications and the CoFHE ecosystem. - -- **FHE.sol**: The Solidity library that enables smart contracts to perform operations on encrypted data. It exposes a comprehensive API for arithmetic, comparison, and logical operations on encrypted values. - -#### Internal Utilities - -- **Task Manager**: Acts as the gateway for all FHE operation requests, validating requests and managing permissions through the Access Control Layer (ACL). - -- **Slim Listener**: Monitors blockchain events and forwards FHE operation requests to the off-chain execution environment. - -- **Result Processor**: Handles FHE operation results from the computation layer and publishes them back to the blockchain. - -- **FHEOS Server**: Executes the actual FHE operations on encrypted data and maintains the encrypted state. - -- **Threshold Network**: A distributed system that securely handles decryption requests through multi-party computation, ensuring no single entity can access the decryption key. - -- **Ciphertext Registry**: Per-host-chain registry that maintains references to encrypted values during a chain's lifecycle. - -- **Commitment Registry**: Single-chain (Arbitrum One) registry where the coprocessor records `(version, handle) β†’ commitHash` entries for every FHE computation result. The Threshold Network reads it to verify ciphertext integrity before issuing a decryption β€” distinct from the host-chain Ciphertext Registry above. - -### Data Flows - -CoFHE implements several critical data flows that maintain privacy throughout the computation lifecycle: - -1. **Encryption Request**: Manages the secure encryption of input data via ZK proofs before it enters the blockchain. - -2. **FHE Operation Flow**: Handles the process of requesting and executing computations on encrypted data. - -3. **Decryption Request**: Processes requests to decrypt data using the Threshold Network. - -4. **Decrypt/Seal Output**: Enables users to access encrypted results while maintaining privacy. - -This architecture ensures that data remains encrypted throughout its entire lifecycle while still enabling complex computations, providing a foundation for privacy-preserving blockchain applications. - +CoFHE (Coprocessor for Fully Homomorphic Encryption) lets smart contracts compute on encrypted data. Contracts request operations through onchain calls; a set of offchain services executes them and commits to the results. Data stays encrypted through the entire lifecycle, and every result can be verified against an onchain commitment. + +```mermaid +flowchart LR + subgraph App["Application"] + SDK["Client SDK"] + end + + subgraph Host["Host chain"] + FHEC["Your contract + FHE.sol"] + TM["TaskManager + ACL"] + PS["PlaintextsStorage"] + end + + subgraph CoFHE["CoFHE services (offchain)"] + ZK["ZK Verifier"] + SL["Slim Listener"] + FheOS["FheOS Server"] + Engine["FHE Engine"] + CTS["Ciphertext Server"] + BP["Blockchain Poster"] + TEE["Teecryptor (TEE)"] + end + + subgraph Registry["Registry chain"] + CR["CommitmentRegistry"] + end + + SDK -- "encrypt input + ZK proof" --> ZK + ZK -- "store ciphertext" --> CTS + FHEC --> TM + TM -- "task events" --> SL + SL --> FheOS + FheOS --> Engine + Engine -- "result commitments" --> BP + BP --> CR + SDK -- "decrypt / sealoutput" --> TEE + TEE -- "ACL check" --> TM + TEE -- "fetch ciphertext" --> CTS + TEE -- "verify commitment" --> CR + SDK -- "publish signed result" --> TM + TM --> PS +``` + +## The onchain contracts + +- **FHE.sol**: the Solidity library your contract imports. It exposes arithmetic, comparison, and logical operations on encrypted values, plus access control (`allow`, `allowGlobal`) and decrypt-result verification. +- **[TaskManager](/deep-dive/cofhe-components/task-manager)**: the gateway for all FHE operation requests. It validates requests, emits task events for the offchain services, and manages permissions through the [ACL](/deep-dive/cofhe-components/acl). +- **[PlaintextsStorage](/deep-dive/cofhe-components/plaintext-storage)**: stores decrypted results after they are published onchain with a verified Teecryptor signature. +- **[CommitmentRegistry](/deep-dive/cofhe-components/commitment-registry)**: lives on a dedicated registry chain and records a hash commitment for every ciphertext the coprocessor produces or verifies. Teecryptor checks it before decrypting anything. + +## The offchain services + +- **[Client SDK](/client-sdk/introduction/overview)** (`@cofhe/sdk`): the TypeScript library applications use to encrypt inputs, manage [permits](/client-sdk/guides/permits), and decrypt outputs. +- **[ZK Verifier](/deep-dive/cofhe-components/zk-verifier)**: verifies the zero-knowledge proof attached to every encrypted input, signs it, and stores the ciphertext bytes. +- **[Slim Listener](/deep-dive/cofhe-components/slim-listener)**: watches TaskManager events on each host chain and forwards them into the coprocessor's queues. +- **[FheOS Server](/deep-dive/cofhe-components/fheos-server)**: ingests task events, verifies inputs, creates result placeholders, and routes work to the FHE Engine. It does not execute FHE operations itself. +- **[FHE Engine](/deep-dive/cofhe-components/fheos-server)**: executes every FHE operation on encrypted data, persists the resulting ciphertexts, and emits a commitment for each result. +- **Ciphertext Server**: stores and serves ciphertext bytes to the other services. +- **Blockchain Poster**: batches result commitments and posts them to the CommitmentRegistry. +- **[Teecryptor](/deep-dive/cofhe-components/teecryptor)**: the decryption service. It runs inside a hardware-attested TEE, authorizes every request against the onchain ACL, verifies the ciphertext commitment, and returns signed or sealed results. + +Services communicate through message queues rather than direct calls, so each stage can retry and scale independently. + +## Data flows + +1. **[Encryption request](/deep-dive/data-flows/encryption-request-flow)**: an input is encrypted client-side and proven valid with a zero-knowledge proof before it enters the chain. +2. **[FHE operation flow](/deep-dive/data-flows/fhe-operation-request-flow)**: a contract requests a computation; the coprocessor executes it and commits to the result. +3. **[Decryption request](/deep-dive/data-flows/decryption-request-flow)**: the SDK asks Teecryptor for a signed plaintext that can be published onchain. +4. **[Offchain decryption](/deep-dive/data-flows/off-chain-decryption-flow)**: the SDK receives the plaintext sealed to a permit, for reads that never touch the chain. + +## What comes next + +Decryption is currently performed by Teecryptor inside a hardware-attested TEE. A multi-party [Threshold Network](/deep-dive/research/future-plans) is the planned successor. From 113335e78c3ac33921939a0f44e6dc6155255187 Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:08:39 +0300 Subject: [PATCH 05/58] [DOCS] deep-dive/fhe-operation-request-flow: rewrite with FHE Engine and commitment leg, replace Transactions.svg with Mermaid --- .../data-flows/fhe-operation-request-flow.mdx | 132 +++++++++--------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/deep-dive/data-flows/fhe-operation-request-flow.mdx b/deep-dive/data-flows/fhe-operation-request-flow.mdx index 434716a..aed4efd 100644 --- a/deep-dive/data-flows/fhe-operation-request-flow.mdx +++ b/deep-dive/data-flows/fhe-operation-request-flow.mdx @@ -1,111 +1,111 @@ --- title: FHE Operation Request Flow sidebar_position: 2 -description: "Complete flow of an FHE operation request in the CoFHE ecosystem through smart contracts" +description: "How an FHE operation travels from a smart contract call through the coprocessor to an onchain commitment" --- -# FHE Operation Request Flow +This page follows a single FHE operation from the contract call that requests it to the commitment that anchors its result onchain. The request itself is synchronous: the contract gets a handle for the result immediately, while the coprocessor computes the actual ciphertext in the background. -## Overview - -This document outlines the complete flow of an FHE (Fully Homomorphic Encryption) operation request in the CoFHE ecosystem through Smart Contracts. Understanding this process is essential for developers integrating private computation capabilities into their smart contracts. - -## Key Components +## Key components | Component | Description | |-----------|-------------| -| **dApp** | The decentralized application that requests FHE operations | -| **FHE.sol** | The library providing FHE operation functions | -| **Task Manager** | Verifies and forwards operation requests | -| **Slim Listener** | Monitors blockchain events and forwards requests to the execution layer | -| **Result Processor** | Handles operation results and publishes them back to the blockchain | -| **fheOS Server** | Executes the actual FHE operations | -| **Threshold Network** | (When applicable) Handles secure decryption operations | - -## Flow Diagram - -The following diagram illustrates the complete flow of an FHE operation request in the CoFHE ecosystem: - - -End-to-end flow of an FHE operation request through the CoFHE system components - - -*Figure 1: End-to-end flow of an FHE operation request through the CoFHE system components* +| **Your contract** | Requests FHE operations through the FHE.sol library | +| **FHE.sol** | The Solidity library providing FHE operation functions | +| **[TaskManager](/deep-dive/cofhe-components/task-manager)** | Validates requests, checks the [ACL](/deep-dive/cofhe-components/acl), and emits task events | +| **[Slim Listener](/deep-dive/cofhe-components/slim-listener)** | Watches TaskManager events on each host chain and enqueues them | +| **[FheOS Server](/deep-dive/cofhe-components/fheos-server)** | Ingests task events, validates them, and routes work to the FHE Engine | +| **[FHE Engine](/deep-dive/cofhe-components/fheos-server)** | Executes the FHE operation and stores the result ciphertext | +| **Blockchain Poster** | Batches result commitments and posts them onchain | +| **[CommitmentRegistry](/deep-dive/cofhe-components/commitment-registry)** | Records a hash commitment for every result ciphertext | + +## Flow diagram + +```mermaid +sequenceDiagram + participant Contract as Your contract (FHE.sol) + participant TM as TaskManager + participant SL as Slim Listener + participant FheOS as FheOS Server + participant Engine as FHE Engine + participant BP as Blockchain Poster + participant CR as CommitmentRegistry + + Contract->>TM: FHE.add(lhs, rhs) calls createTask + TM->>TM: validate inputs, check ACL + TM-->>Contract: result handle (synchronous) + TM->>SL: TaskCreated event + SL->>FheOS: blockchain-events queue + FheOS->>Engine: engine-requests queue + Engine->>Engine: execute op, store ciphertext under the handle + Engine->>BP: commitment-requests queue + BP->>CR: postCommitments (batched) +``` -## Step-by-Step Flow +## Step-by-step flow - -The decentralized application (dApp) integrates with CoFHE by utilizing the **Client SDK** (`@cofhe/sdk`) for encryption. - -[See in GitHub](https://github.com/FhenixProtocol/cofhesdk) 1️⃣ - -[Encrypt request](/deep-dive/data-flows/encryption-request-flow) using the Client SDK, returns `InEuint` structure. + +The application encrypts its input client-side with the [Client SDK](/client-sdk/introduction/overview) (`@cofhe/sdk`) and proves it valid, producing an `InEuint` structure the contract can accept. The [Encryption Request Flow](/deep-dive/data-flows/encryption-request-flow) covers this step. -This step happens on the client side before blockchain interaction. +This step happens on the client side, before any blockchain interaction. - -When the dApp needs to perform an encrypted operation within the smart contract: 2️⃣ - -**Import the FHE library in Solidity:** + +Import the FHE library in Solidity: ```solidity import "@fhenixprotocol/cofhe-contracts/FHE.sol"; ``` -**Call the appropriate FHE function** from the imported library: +Call the appropriate FHE function from the imported library: ```solidity -// using trivial encrypt or the returned structures from the previous step. -function addExample(InEuint32 encryptedInput) { +// Using trivial encrypt or the structure returned by the previous step. +function addExample(InEuint32 memory encryptedInput) public { euint32 lhs = FHE.asEuint32(encryptedInput); euint32 rhs = FHE.asEuint32(10); - + // Request an operation (addition in this example) euint32 result = FHE.add(lhs, rhs); } ``` -**FHE.sol forwards the request** to the Task Manager contract +FHE.sol forwards the request to the TaskManager contract. - -The Task Manager serves as the gateway for all FHE operation requests: + +The TaskManager is the gateway for all FHE operation requests. It: -1. **Validate request structure** to ensure all inputs are properly formatted -2. **Verify access permissions** by checking if the caller has proper access to the encrypted inputs (using ACL.sol) 3️⃣ -3. **Generate a unique handle** that will be used to reference the future ciphertext result -4. **Return the handle** to the calling dApp contract -5. **Emit an event** containing the operation details for the Slim Listener to process 4️⃣ +1. Validates the request structure, so all inputs are properly formatted. +2. Verifies access permissions: the caller must have ACL access to every encrypted input. +3. Generates a unique handle that will reference the future ciphertext result. +4. Returns the handle to the calling contract, synchronously. Subsequent operations can chain on it right away. +5. Emits a `TaskCreated` event with the operation details for the offchain services. - -The Slim Listener monitors and forwards FHE operation requests: + +One Slim Listener instance runs per host chain. It watches for `TaskCreated` events and publishes them to the coprocessor's `blockchain-events` queue. + -1. **Listen for events** from the Task Manager 5️⃣ -2. **Forward request details** to the fheOS server 6️⃣ + +The FheOS Server consumes `blockchain-events`, validates the task, and routes FHE operations to the `engine-requests` queue. It does not execute operations itself. - -The FheOS server handles requests: + +The FHE Engine consumes `engine-requests` and: -1. **Create execution thread** on the fheOS server -2. **Execute the requested operation** on encrypted data -3. **Generate result ciphertext** containing the encrypted result -4. **Map the handle** to the actual ciphertext hash in the private storage -5. **Make result available** for subsequent operations -6. **Notify the Result Processor** of operation completion +1. Executes the requested operation on the encrypted data. +2. Stores the result ciphertext in the coprocessor's store, keyed by the handle. +3. Resolves any queued operations that were waiting on this handle. +4. Publishes a commitment for the result (the hash of the stored ciphertext bytes) to the `commitment-requests` queue. - -For standard FHE operations (not decryption): - -1. **Update ciphertext registry** with the new encrypted result 7️⃣ + +The Blockchain Poster batches commitments and posts them to the CommitmentRegistry on the registry chain. The commitment anchors the result. Teecryptor will only decrypt ciphertext bytes that hash to a registered commitment. -At this point **the operation cycle is completed**, preserving the confidentiality of all encrypted values. +At this point the operation cycle is complete, and the confidentiality of every encrypted value is preserved. - From 8de03761618b553eb4320cb07e48626ee1383ce6 Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:11:24 +0300 Subject: [PATCH 06/58] [DOCS] deep-dive/encryption-request-flow: rewrite around encryptInputs and the ZK Verifier, replace Encrypt-a-value.svg with Mermaid --- .../data-flows/encryption-request-flow.mdx | 78 +++++++++++-------- 1 file changed, 45 insertions(+), 33 deletions(-) diff --git a/deep-dive/data-flows/encryption-request-flow.mdx b/deep-dive/data-flows/encryption-request-flow.mdx index 491f29f..af3fbf3 100644 --- a/deep-dive/data-flows/encryption-request-flow.mdx +++ b/deep-dive/data-flows/encryption-request-flow.mdx @@ -1,35 +1,46 @@ --- title: Encryption Request Flow -description: "Complete flow of the encryption request process using the Client SDK for encrypting data for private computation with smart contracts" +description: "How a plaintext becomes a verified encrypted input: local encryption, ZK proof, verification, and onchain use" --- -## Overview +This page follows an encrypted input from the plaintext in your application to a handle a smart contract can compute on. Everything sensitive happens client-side: the value is encrypted and proven locally, and only the ciphertext and its proof ever leave the user's machine. -This document outlines the complete flow of the encryption request process using the `@cofhe/sdk` Client SDK, a TypeScript library designed to help users encrypt data for private computation with smart contracts. Understanding this process is essential for developers who want to enable their users to interact with privacy-preserving smart contracts using encrypted inputs. - -## Key Components +## Key components | Component | Description | |-----------|-------------| -| **dApp** | The decentralized application that interacts with the user and the contracts | -| **Client SDK** (`@cofhe/sdk`) | TypeScript package designed for seamless interaction with Fhenix's co-processor | -| **Threshold Network** | (When applicable) Handles secure decryption operations | - -## Flow Diagram - -The following diagram illustrates the complete flow of an Encryption request in the CoFHE ecosystem: - - -End-to-end flow of an Encryption request through the CoFHE system components - - -*Figure 1: End-to-end flow of an Encryption request through the CoFHE system components* +| **dApp** | The application that interacts with the user and the contracts | +| **Client SDK** (`@cofhe/sdk`) | TypeScript library that encrypts inputs locally and submits them for verification | +| **ZK Verifier** | Attested offchain service that verifies the proof attached to every encrypted input | +| **Ciphertext Server** | Stores the verified ciphertext bytes for the coprocessor | +| **[TaskManager](/deep-dive/cofhe-components/task-manager)** | Verifies the ZK Verifier's signature when the input is used onchain | + +## Flow diagram + +```mermaid +sequenceDiagram + participant App as Your app + participant SDK as Client SDK + participant ZK as ZK Verifier + participant CTS as Ciphertext Server + participant TM as TaskManager (host chain) + + App->>SDK: encryptInputs([...]).execute() + SDK->>SDK: encrypt with TFHE, generate zkPoK + SDK->>ZK: ciphertext + proof + ZK->>ZK: verify the proof in the attested TEE + ZK->>CTS: store ciphertext bytes + ZK-->>SDK: handle + signature per input + SDK-->>App: encrypted inputs (InEuint structures) + App->>TM: contract call with the encrypted input + TM->>TM: verify signature, emit InputVerified +``` -## Step-by-Step Flow +## Step-by-step flow -Install, include and initialize the Client SDK in your project (full details [here](/client-sdk/introduction/installation)). +Install and initialize the Client SDK in your project. Full details are in the [installation guide](/client-sdk/introduction/installation). ```bash npm install @cofhe/sdk @@ -41,26 +52,27 @@ const { createCofheConfig, createCofheClient } = require("@cofhe/sdk/node"); ``` - -1️⃣ The data is encrypted locally using the `encrypt` function. + +The application encrypts its values with a single builder call: -Under the hood, `encrypt` encrypts the data using the TFHE library and create a zkPoK to prove the encryption is correct. - - - -The zkPoK is verified using the `verify` function. 2️⃣ +```typescript +const [encryptedInput] = await cofheClient + .encryptInputs([Encryptable.uint32(42n)]) + .execute(); +``` -This verification process ensures that the ciphertext was generated correctlyβ€”that it represents a valid encryption of a known plaintextβ€”and that the data has not been tampered with. Upon successful verification, the encrypted data is stored in the Data Availability (DA) layer. 3️⃣ 4️⃣ +Internally, `encryptInputs` encrypts each value with the TFHE library and generates a zkPoK (zero-knowledge proof of knowledge) that the encryption is correct. It then submits the ciphertext and proof to the ZK Verifier. + -The function returns a value handle that can be used to reference the encrypted data later, along with a signature. 5️⃣ + +The ZK Verifier checks the proof inside its attested enclave. A valid proof shows the ciphertext is a correct, untampered encryption of a known plaintext. On success, the verifier stores the ciphertext bytes and returns a handle and a signature per input. The SDK packages these into the `InEuint` structures your contract accepts. - -The user can send the value handle to the contract as an encrypted input. This handle represents the ciphertext stored in the DA layer and allows the contract to reference the encrypted value. + +The application passes the `InEuint` structure to the contract as an encrypted input. When the contract consumes it, the TaskManager verifies the ZK Verifier's signature and emits an `InputVerified` event. The coprocessor picks that event up and posts a commitment for the input to the CommitmentRegistry, so the ciphertext is anchored onchain like every computed result. -Read more about the implementation details [here](/client-sdk/guides/encrypting-inputs) +Read more about the client-side API in [Encrypting Inputs](/client-sdk/guides/encrypting-inputs). - From 31858b4d90ec6b950d0a63ca0b967788f2f6f564 Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:18:35 +0300 Subject: [PATCH 07/58] [DOCS] deep-dive/fheos-server: rewrite as ingestion and orchestration service, execution moved to FHE Engine --- deep-dive/cofhe-components/fheos-server.mdx | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/deep-dive/cofhe-components/fheos-server.mdx b/deep-dive/cofhe-components/fheos-server.mdx index 2c544f4..bbf7228 100644 --- a/deep-dive/cofhe-components/fheos-server.mdx +++ b/deep-dive/cofhe-components/fheos-server.mdx @@ -1,13 +1,20 @@ --- -title: FheOs - Server -description: "Off-chain computational layer that executes FHE operations and manages encrypted computations" +title: FheOS Server +description: "Offchain ingestion service that validates task events and orchestrates work for the FHE Engine" --- | Aspect | Description | |---------|-------------| -| **Type** | Off-chain computational layer. | -| **Function** | Executes FHE operations and manages encrypted computations | -| **Responsibilities** | β€’ Receives the request from the Slim Listener
β€’ Executes the FHE operations
β€’ Calls Result Processor when result is created
β€’ Returns plaintext results when requested (i.e decrypt/seal output), preserving privacy throughout the pipeline | +| **Type** | Offchain ingestion and orchestration service. | +| **Function** | Validates task events and routes work to the [FHE Engine](/deep-dive/cofhe-components/fhe-engine). | +| **Responsibilities** | β€’ Consumes task events from the `blockchain-events` queue
β€’ Validates each operation and its encrypted inputs
β€’ Creates a placeholder record for every result handle
β€’ Routes validated FHE operations to the `engine-requests` queue | -The FHE Operating System server manages the execution environment for FHE operations. +The FheOS Server sits between the chain and the execution layer. [Slim Listeners](/deep-dive/cofhe-components/slim-listener) publish TaskManager events into the `blockchain-events` queue. The FheOS Server consumes them, checks that each operation is well formed and its inputs exist, and enqueues the validated work for the FHE Engine. It does not execute FHE operations itself, and it exposes no API beyond a health endpoint. +## Ordering and failure handling + +Operations can arrive before the inputs they depend on have finished computing. The FheOS Server defers such operations and releases them once the missing results land, so out-of-order delivery never produces a wrong answer. Messages that are malformed or reference inputs that never materialize are routed to a dead-letter queue instead of being silently dropped. + +## What it is not + +The FheOS Server is frequently mistaken for the execution engine. Execution happens in the [FHE Engine](/deep-dive/cofhe-components/fhe-engine), and decryption happens in [Teecryptor](/deep-dive/cofhe-components/teecryptor). The FheOS Server verifies and orchestrates. From f9872bf834fe5f786016d1e18f6b883bfa7a75e4 Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:18:35 +0300 Subject: [PATCH 08/58] [DOCS] deep-dive/fhe-engine: new page for the execution service, added to nav --- deep-dive/cofhe-components/fhe-engine.mdx | 24 +++++++++++++++++++++++ docs.json | 1 + 2 files changed, 25 insertions(+) create mode 100644 deep-dive/cofhe-components/fhe-engine.mdx diff --git a/deep-dive/cofhe-components/fhe-engine.mdx b/deep-dive/cofhe-components/fhe-engine.mdx new file mode 100644 index 0000000..413477f --- /dev/null +++ b/deep-dive/cofhe-components/fhe-engine.mdx @@ -0,0 +1,24 @@ +--- +title: FHE Engine +description: "Offchain execution service that runs every FHE operation and commits to its results" +--- + +| Aspect | Description | +|---------|-------------| +| **Type** | Offchain execution service. | +| **Function** | Executes every FHE operation and persists the encrypted results. | +| **Responsibilities** | β€’ Consumes validated work from `engine-requests`
β€’ Executes the operation with the TFHE library
β€’ Stores each result ciphertext by handle
β€’ Publishes a hash commitment for every result | + +The FHE Engine is where computation actually happens. It consumes the work the [FheOS Server](/deep-dive/cofhe-components/fheos-server) validated and runs the requested operation (arithmetic, comparison, select, cast, random) on the encrypted operands. The result ciphertext is stored under the handle the TaskManager issued, and operations that were waiting on that handle are released as soon as it lands. + +FHE operations are computationally heavy, so the engine bounds how many run concurrently and scales horizontally behind the queue. Backpressure lives in the queue, not in dropped work. + +## Result commitments + +For every stored result, the engine publishes a commitment (the keccak256 hash of the stored ciphertext bytes) to the `commitment-requests` queue. The Blockchain Poster batches these and posts them to the [CommitmentRegistry](/deep-dive/cofhe-components/commitment-registry). This is the anchor [Teecryptor](/deep-dive/cofhe-components/teecryptor) verifies before decrypting anything: only bytes that hash to a registered commitment ever reach the decryption key. + +## Key material + +The engine computes with the FHE public key material only. Production builds load no decryption key, so a compromised engine can corrupt results (which commitment verification would catch) but cannot read them. Decryption capability exists solely inside [Teecryptor](/deep-dive/cofhe-components/teecryptor)'s attested enclave. + +The engine also serves the public encryption parameters that clients need: the network public key and the CRS (common reference string) used to build encryption proofs. diff --git a/docs.json b/docs.json index 2d604ef..a03f619 100644 --- a/docs.json +++ b/docs.json @@ -245,6 +245,7 @@ "deep-dive/cofhe-components/commitment-registry", "deep-dive/cofhe-components/zk-verifier", "deep-dive/cofhe-components/fheos-server", + "deep-dive/cofhe-components/fhe-engine", "deep-dive/cofhe-components/threshold-network" ] }, From 5dd536edac687b24ad43fa7a801d4f7225b1a6c7 Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:21:12 +0300 Subject: [PATCH 09/58] [DOCS] deep-dive/commitment-registry: Teecryptor as commitment enforcer, drop chain naming, style-guide compliance --- .../cofhe-components/commitment-registry.mdx | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/deep-dive/cofhe-components/commitment-registry.mdx b/deep-dive/cofhe-components/commitment-registry.mdx index 9b22146..73a22bf 100644 --- a/deep-dive/cofhe-components/commitment-registry.mdx +++ b/deep-dive/cofhe-components/commitment-registry.mdx @@ -1,20 +1,18 @@ --- title: CommitmentRegistry -description: "Registry-chain contract that records FHE computation commitments. The Threshold Network reads it to verify ciphertext integrity before decrypting." +description: "Registry-chain contract that records FHE computation commitments. Teecryptor verifies ciphertext integrity against it before decrypting." --- | Aspect | Description | |--------|-------------| -| **Type** | UUPS-upgradeable Solidity contract deployed on a **registry chain** (Arbitrum One in production). Distinct from the per-host-chain [CTRegistry](/deep-dive/cofhe-components/ct-registry). | +| **Type** | UUPS-upgradeable Solidity contract deployed on a dedicated **registry chain**. | | **Function** | Records `(version, handle) β†’ commitHash` entries for every FHE operation result that the coprocessor produces. | -| **Responsibilities** | β€’ Provide an authoritative source of ciphertext integrity that the Threshold Network checks **before** issuing a decryption.
β€’ Group commitments by an opaque `version` tag so a future tfhe-rs / FHE-parameter upgrade can roll out without invalidating earlier ciphertexts.
β€’ Enforce write-once semantics per `(version, handle)` to prevent commitment replacement.
β€’ Expose paginated enumeration so off-chain tooling can audit what has been posted. | -| **Deployment** | One deployment per registry chain, behind an ERC-1967 proxy. Initialized with `(initialOwner, initialPoster)`. Owner is `Ownable2Step` β€” transfers require explicit accept. | +| **Responsibilities** | β€’ Provide an authoritative source of ciphertext integrity that [Teecryptor](/deep-dive/cofhe-components/teecryptor) checks **before** decrypting.
β€’ Group commitments by an opaque `version` tag so a future tfhe-rs / FHE-parameter upgrade can roll out without invalidating earlier ciphertexts.
β€’ Enforce write-once semantics per `(version, handle)` to prevent commitment replacement.
β€’ Expose paginated enumeration so offchain tooling can audit what has been posted. | +| **Deployment** | One deployment per registry chain, behind an ERC-1967 proxy. Initialized with `(initialOwner, initialPoster)`. Owner is `Ownable2Step`; transfers require an explicit accept. | ## Why a separate registry chain? -The Threshold Network needs to confirm that the ciphertext it's about to decrypt is **exactly** the one the FHE Engine produced (not a tampered or stale handle). The natural place to anchor that proof is on-chain, but doing it on every host chain would force the network to maintain N RPC paths and pay gas on N chains for every FHE operation. Instead, the coprocessor posts commitments to a **single registry chain** (currently Arbitrum One), and the Threshold Network only watches that one. - -This is why the host-chain [CTRegistry](/deep-dive/cofhe-components/ct-registry) (which maps temporary β†’ final ciphertext hashes inside one chain's lifecycle) and `CommitmentRegistry` (which records the canonical commitment for every produced ciphertext, cross-chain) are deliberately distinct components. +[Teecryptor](/deep-dive/cofhe-components/teecryptor) needs to confirm that the ciphertext it is about to decrypt is **exactly** the one the FHE Engine produced, not a tampered or stale handle. The natural place to anchor that proof is onchain, but anchoring on every host chain would mean paying gas on N chains for every FHE operation. Instead, the coprocessor posts commitments to a **single registry chain**, and the decryption path watches only that one. ## Storage shape @@ -29,21 +27,22 @@ mapping(address => bool) poster ## Version lifecycle -`version` is an opaque `bytes32` tag chosen by the coprocessor when FHE parameters change (see [the FHE Engine `COMMITMENT_VERSION` notes](https://github.com/FhenixProtocol/cofhe/blob/master/CHANGELOG.md#060---2026-05-05)). Every version moves through a small state machine: +`version` is an opaque `bytes32` tag chosen by the coprocessor when FHE parameters change, currently the ASCII tag `"2"` (see [the FHE Engine `COMMITMENT_VERSION` notes](https://github.com/FhenixProtocol/cofhe/blob/master/CHANGELOG.md#060---2026-05-05)). Every version moves through a small state machine: -``` -Unset ─┐ - β–Ό - Active ─┬──────► Deprecated ──► Revoked - └─────────────────────► Revoked +```mermaid +stateDiagram-v2 + Unset --> Active + Active --> Deprecated + Active --> Revoked + Deprecated --> Revoked ``` | State | Meaning | Allowed transitions | |-------|---------|---------------------| -| `Unset` | Default. No commitments have been posted under this version. | β†’ `Active` | -| `Active` | Posters may write commitments under this version. The Threshold Network honors lookups. | β†’ `Deprecated`, β†’ `Revoked` | -| `Deprecated` | New commitments rejected. Existing lookups still resolve. Used during a parameter rollover. | β†’ `Revoked` | -| `Revoked` | Hard kill. No further transitions; the version is dead. | β€” (terminal) | +| `Unset` | Default. No commitments have been posted under this version. | to `Active` | +| `Active` | Posters may write commitments under this version. Teecryptor honors lookups. | to `Deprecated` or `Revoked` | +| `Deprecated` | New commitments rejected. Existing lookups still resolve. Used during a parameter rollover. | to `Revoked` | +| `Revoked` | Hard kill. No further transitions; the version is dead. | none (terminal) | Owner-only `setVersionStatus(version, newStatus)` enforces these transitions and reverts with `InvalidVersionTransition` otherwise. The transition emits `VersionStatusChanged(version, oldStatus, newStatus)`. @@ -54,7 +53,7 @@ Owner-only `setVersionStatus(version, newStatus)` enforces these transitions and | **Owner** | `initialize(initialOwner, …)`, then `Ownable2Step` transfer. | `addPoster`, `removePoster`, `setVersionStatus`, `_authorizeUpgrade`. | | **Poster** | Owner-only `addPoster(address)`. Initial poster supplied to `initialize`. | `postCommitments`, `postCommitmentsSafe`. | -Non-poster posts revert with `OnlyPosterAllowed(caller)`. In production, the [`blockchain-poster`](https://github.com/FhenixProtocol/cofhe/blob/master/CHANGELOG.md#060---2026-05-05) service holds the only poster role and signs through OpenZeppelin Relayer. +Non-poster posts revert with `OnlyPosterAllowed(caller)`. In production, the poster role is held by the [`blockchain-poster`](https://github.com/FhenixProtocol/cofhe/blob/master/CHANGELOG.md#060---2026-05-05) service's relayer signer (OpenZeppelin Relayer). ## Writing commitments @@ -74,20 +73,20 @@ function postCommitmentsSafe( Both functions batch-write `(version, handle) β†’ commitHash` rows and require: -- `version` is in `Active` state β€” otherwise reverts with `VersionNotActive(version)`. -- `handles.length == commitHashes.length` and `> 0` β€” otherwise `LengthMismatch` / `EmptyBatch`. -- Each `commitHash != bytes32(0)` β€” otherwise `ZeroCommitHash(handle)`. +- `version` is in `Active` state, otherwise the call reverts with `VersionNotActive(version)`. +- `handles.length == commitHashes.length` and `> 0`, otherwise `LengthMismatch` / `EmptyBatch`. +- Each `commitHash != bytes32(0)`, otherwise `ZeroCommitHash(handle)`. The difference is in **how duplicates are handled**: | Function | Duplicate handle under same version | Use case | |----------|-------------------------------------|----------| -| `postCommitments` | Reverts the whole batch with `CommitmentAlreadyExists(version, handle)`. | Strict integrity β€” caller knows it's posting unique data. | +| `postCommitments` | Reverts the whole batch with `CommitmentAlreadyExists(version, handle)`. | Strict integrity: the caller knows it is posting unique data. | | `postCommitmentsSafe` | Silently skips the handle; emits `CommitmentsPostedSafe(version, newlyPosted, skipped)`. | Idempotent re-flushes (e.g. when the coprocessor's message broker redelivers a commitment batch). | -`postCommitments` emits `CommitmentsPosted(version, batchSize)`. `postCommitmentsSafe` emits `CommitmentsPostedSafe(version, newlyPosted, skipped)` so the off-chain caller can tell whether the round did real work. +`postCommitments` emits `CommitmentsPosted(version, batchSize)`. `postCommitmentsSafe` emits `CommitmentsPostedSafe(version, newlyPosted, skipped)` so the offchain caller can tell whether the round did real work. -Both enforce **write-once per (version, handle)** β€” a commitment can never be overwritten, only superseded by writing the same handle under a new `version`. +Both enforce **write-once per (version, handle)**: a commitment can never be overwritten, only superseded by writing the same handle under a new `version`. ## Reading commitments @@ -98,9 +97,9 @@ Both enforce **write-once per (version, handle)** β€” a commitment can never be | `getSize(version)` | `uint256` | Number of handles ever committed under `version`. | | `getHandleByIndex(version, index)` | `bytes32` | Direct array lookup. Reverts on out-of-range. | | `getHandles(version, offset, limit)` | `bytes32[]` | Paginated. Returns an empty array if `offset >= total`; clamps `offset + limit` at `total`. | -| `isPoster(address)` | `bool` | Useful for off-chain ops dashboards. | +| `isPoster(address)` | `bool` | Useful for offchain ops dashboards. | -The paginated `getHandles` is the recommended way to enumerate a version β€” `getSize` first to compute pages, then `getHandles(version, offset, pageSize)` in a loop. +The paginated `getHandles` is the recommended way to enumerate a version: `getSize` first to compute pages, then `getHandles(version, offset, pageSize)` in a loop. ## Events @@ -113,10 +112,10 @@ The paginated `getHandles` is the recommended way to enumerate a version β€” `ge ## Upgrades -The contract is `UUPSUpgradeable`. `_authorizeUpgrade` is gated by `onlyOwner`. The constructor calls `_disableInitializers()` so the implementation contract itself can never be initialized β€” initialization happens through the proxy via `initialize(initialOwner, initialPoster)`. +The contract is `UUPSUpgradeable`. `_authorizeUpgrade` is gated by `onlyOwner`. The constructor calls `_disableInitializers()` so the implementation contract itself can never be initialized; initialization happens through the proxy via `initialize(initialOwner, initialPoster)`. ## Source - Solidity: [`contracts/internal/registry-chain/contracts/commitment-registry/CommitmentRegistry.sol`](https://github.com/FhenixProtocol/cofhe-contracts/blob/master/contracts/internal/registry-chain/contracts/commitment-registry/CommitmentRegistry.sol). -- Off-chain poster service: [`src/services/blockchain-poster/`](https://github.com/FhenixProtocol/cofhe/tree/master/src/services/blockchain-poster) β€” introduced in [cofhe `0.6.0`](https://github.com/FhenixProtocol/cofhe/blob/master/CHANGELOG.md#060---2026-05-05). +- Offchain poster service: [`src/services/blockchain-poster/`](https://github.com/FhenixProtocol/cofhe/tree/master/src/services/blockchain-poster), introduced in [cofhe `0.6.0`](https://github.com/FhenixProtocol/cofhe/blob/master/CHANGELOG.md#060---2026-05-05). - FHE Engine commitment-version bumping: [`fhe-engine/src/rabbitmq/handlers.rs`](https://github.com/FhenixProtocol/cofhe/blob/master/fhe-engine/src/rabbitmq/handlers.rs). From 2cc4cac065d9b921635507b45b9b5ef48c8852a3 Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:22:39 +0300 Subject: [PATCH 10/58] [DOCS] deep-dive/task-manager: two-signer model, publish gating, result getters, upgrade notes --- deep-dive/cofhe-components/task-manager.mdx | 44 +++++++++++++-------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/deep-dive/cofhe-components/task-manager.mdx b/deep-dive/cofhe-components/task-manager.mdx index 19df020..5530824 100644 --- a/deep-dive/cofhe-components/task-manager.mdx +++ b/deep-dive/cofhe-components/task-manager.mdx @@ -1,37 +1,45 @@ --- title: TaskManager -description: "On-chain entry point for CoFHE integration that initiates FHE operations, generates unique handles, and verifies decrypt result signatures" +description: "Onchain entry point for CoFHE integration that initiates FHE operations, generates unique handles, and verifies decrypt result signatures" --- - | Aspect | Description | |---------|-------------| -| **Type** | Contract deployed on the destination blockchain | -| **Function** | Acts as the on-chain entry point for CoFHE integration | -| **Responsibilities** | β€’ Initiates FHE operations by serving as the on-chain entry point. The dApp contract calls the FHE.sol library which triggers the TaskManager contract to submit a new encrypted computation task.
β€’ Generates unique handles that act as references to the results of FHE operations. These results are computed asynchronously off-chain.
β€’ Emits structured events containing the unique handle of the ciphertext, operation type, and other required metadata.
β€’ Verifies ECDSA signatures on client-published decrypt results and stores them on-chain. | -| **Deployment** | A separate Task Manager Contract is deployed for each supported destination chain, enabling chain-specific integrations | +| **Type** | Contract deployed on the host chain, UUPS-upgradeable behind a proxy. | +| **Function** | Acts as the onchain entry point for CoFHE integration. | +| **Responsibilities** | β€’ Initiates FHE operations requested through the `FHE.sol` library.
β€’ Generates the unique handles that reference future FHE results.
β€’ Emits structured task events for the offchain services.
β€’ Verifies the signatures on encrypted inputs and published decrypt results. | +| **Deployment** | A separate TaskManager contract is deployed on each supported host chain, enabling chain-specific integrations. | -## Decrypt Result Signature Verification +## Two signers -The TaskManager supports **permissionless publishing of decrypt results**. Anyone holding a valid ECDSA signature from the Threshold Network's Dispatcher can publish a decrypt result on-chain. The TaskManager verifies the signature before storing the result. +The TaskManager holds two distinct signer addresses, one per trust boundary: -### Key State +| Signer | Verifies | Set by | +|--------|----------|--------| +| `verifierSigner` | Encrypted inputs: the ZK Verifier signs each input it verified, and `verifyInput` checks that signature before emitting `InputVerified(ctHash, commitment)`. | Owner | +| `decryptResultSigner` | Decrypt results: [Teecryptor](/deep-dive/cofhe-components/teecryptor) signs each plaintext it returns, and the publish path checks that signature before storing the result. | Owner | -| Variable | Description | -|----------|-------------| -| `decryptResultSigner` | Address of the authorized Threshold Network signer. Set to `address(0)` to skip verification (debug mode). | +Either signer set to `address(0)` skips its verification (debug mode only, never in production). + +## Decrypt result signature verification + +The TaskManager supports **permissionless publishing of decrypt results**. Anyone holding a valid signature from the decryption service can publish the result onchain, provided the contract is enabled (the owner holds an `isEnabled` kill switch). Today that signature comes from Teecryptor; a decentralized [Threshold Network](/deep-dive/research/future-plans) is the planned successor. + +Verified results are stored in the [PlaintextsStorage](/deep-dive/cofhe-components/plaintext-storage) contract, where any contract can read them back with `getDecryptResult` (reverts with `DecryptionResultNotReady` if pending) or `getDecryptResultSafe` (returns a ready flag). ### Functions | Function | Description | |----------|-------------| -| `publishDecryptResult(ctHash, result, signature)` | Verify signature and store the decrypt result on-chain. Emits `DecryptionResult`. | +| `publishDecryptResult(ctHash, result, signature)` | Verify the signature and store the decrypt result onchain. Emits `DecryptionResult`. | | `publishDecryptResultBatch(ctHashes[], results[], signatures[])` | Batch publish multiple results in one transaction for gas efficiency. | | `verifyDecryptResult(ctHash, result, signature)` | Verify a signature without publishing (view). Reverts on failure. | | `verifyDecryptResultSafe(ctHash, result, signature)` | Verify a signature without publishing (view). Returns `false` on failure. | -| `setDecryptResultSigner(address)` | Admin-only. Set the authorized signer address. | +| `verifyDecryptResultBatch(ctHashes[], results[], signatures[])` | Batch verify (view). Reverts on the first failure. | +| `verifyDecryptResultBatchSafe(ctHashes[], results[], signatures[])` | Batch verify (view). Returns a `bool[]` of per-item outcomes. | +| `setDecryptResultSigner(address)` | Owner-only (two-step ownable). Set the authorized signer address. | -### Signature Message Format +### Signature message format The signed message is a fixed **76-byte** buffer: @@ -42,4 +50,8 @@ The signed message is a fixed **76-byte** buffer: | `chain_id` | 8 bytes | u64, big-endian (from `block.chainid`) | | `ct_hash` | 32 bytes | uint256, big-endian | -The message is hashed with `keccak256` and verified using OpenZeppelin's `ECDSA.tryRecover`. The `enc_type` and `chain_id` are derived on-chain, binding each signature to a specific ciphertext type and chain. +The message is hashed with `keccak256` and verified using OpenZeppelin's `ECDSA.tryRecover`. The `enc_type` and `chain_id` are derived onchain, binding each signature to a specific ciphertext type and chain. + +## Upgrades + +The contract is `UUPSUpgradeable` with `_authorizeUpgrade` gated to the owner, and ownership is `Ownable2Step` (transfers require an explicit accept). The constructor calls `_disableInitializers()`, so the implementation contract can never be initialized directly. From dc13e829ef532dbd968c68bffacb7ee92f48a20a Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:24:49 +0300 Subject: [PATCH 11/58] [DOCS] deep-dive/acl: expand with grant tiers, TaskManager-only writes, read surface --- deep-dive/cofhe-components/acl.mdx | 39 +++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/deep-dive/cofhe-components/acl.mdx b/deep-dive/cofhe-components/acl.mdx index 140b31f..9bca2b0 100644 --- a/deep-dive/cofhe-components/acl.mdx +++ b/deep-dive/cofhe-components/acl.mdx @@ -1,11 +1,42 @@ --- title: ACL (Access Control Layer) -description: "On-chain contract that manages and enforces access control for ciphertexts, ensuring only authorized contracts can reference or decrypt them" +description: "Onchain contract that manages and enforces access control for ciphertexts, ensuring only authorized contracts and accounts can reference or decrypt them" --- | Aspect | Description | |--------|-------------| -| **Type** | Contract deployed on the destination blockchain | -| **Function** | Manages and enforces access control for ciphertexts, ensuring only authorized contracts can reference or decrypt them. | -| **Responsibilities** | An internal contract that is responsible for managing and verifying access for each and every ciphertext. | +| **Type** | Contract deployed on the host chain, UUPS-upgradeable behind a proxy. | +| **Function** | Manages and enforces access control for ciphertexts, for both contracts and user accounts. | +| **Responsibilities** | β€’ Records who may use each handle in FHE operations.
β€’ Records which handles may be decrypted, and by whom.
β€’ Answers the access queries of the [TaskManager](/deep-dive/cofhe-components/task-manager) and the decryption service. | +Every encrypted value in CoFHE is guarded by this contract. A handle is useless to anyone the ACL does not list. The TaskManager rejects operations on inputs the caller cannot access, and [Teecryptor](/deep-dive/cofhe-components/teecryptor) refuses to decrypt handles without a matching grant. + +## Grant tiers + +| Tier | Granted by | Scope | +|------|------------|-------| +| **Transient** | `FHE.allowTransient` | Current transaction only. Stored with EIP-1153 transient storage, so it costs no persistent state. | +| **Persistent** | `FHE.allow(handle, account)` | A specific account (contract or EOA), permanently. | +| **Global** | `FHE.allowGlobal` (alias `FHE.allowPublic`) | Every account. Also marks the handle publicly decryptable. | +| **Decryption** | `TaskManager.allowForDecryption` | Adds the handle to the decryption allowlist and emits `AllowedForDecryption`. | + +## Writes go through the TaskManager + +All state-mutating entry points require `msg.sender` to be the TaskManager; direct calls revert with `DirectAllowForbidden`. Contracts grant access through the `FHE.sol` helpers (`allow`, `allowThis`, `allowSender`, `allowGlobal`, `allowTransient`), which route through the TaskManager. + +## Read surface + +| Function | Answers | +|----------|---------| +| `isAllowed(handle, account)` | May this account use the handle? (any tier) | +| `allowedTransient(handle, account)` | Is there a transient grant in this transaction? | +| `persistAllowed(handle, account)` | Is there a persistent grant? | +| `globalAllowed(handle)` | Is the handle globally allowed? | +| `isAllowedForDecryption(handle)` | Is the handle on the decryption allowlist? | +| `isAllowedWithPermission(permission, handle)` | Does this EIP-712 [permit](/client-sdk/guides/permits) authorize its issuer for the handle? | + +The last two are what the decryption path runs on. For every `decrypt` or `sealoutput` request, Teecryptor queries the ACL through the TaskManager: `isAllowedWithPermission` when a permit is attached, or the public-decryptability check when none is. A future [Threshold Network](/deep-dive/research/future-plans) will consume the same interface. + +## Upgrades + +The contract is `UUPSUpgradeable` with owner-gated `_authorizeUpgrade`, ownership is `Ownable2Step`, and storage uses ERC-7201 namespaced slots for upgrade safety. From 0686ff462c3e7cb073b9b39171eb5f129ecee468 Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:27:39 +0300 Subject: [PATCH 12/58] [DOCS] deep-dive/zk-verifier: attested TEE as current, real post-verify path, signature format --- deep-dive/cofhe-components/zk-verifier.mdx | 55 ++++++++++++---------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/deep-dive/cofhe-components/zk-verifier.mdx b/deep-dive/cofhe-components/zk-verifier.mdx index c847d16..f75f435 100644 --- a/deep-dive/cofhe-components/zk-verifier.mdx +++ b/deep-dive/cofhe-components/zk-verifier.mdx @@ -1,56 +1,63 @@ --- title: ZK Verifier -description: "Off-chain service that verifies user inputs using Zero-Knowledge Proofs of Knowledge (ZKPoK) to ensure encrypted data is safe to use in smart contracts" +description: "Offchain service that verifies user inputs using Zero-Knowledge Proofs of Knowledge (ZKPoK) to ensure encrypted data is safe to use in smart contracts" --- -**ZK-Verifier** is an essential component for encrypting and providing data as inputs to confidential smart contracts. +**ZK Verifier** is an essential component for encrypting and providing data as inputs to confidential smart contracts. | Aspect | Description | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Type** | Off-chain service, used by clients. | +| **Type** | Offchain service running inside a hardware-attested TEE, used by clients. | | **Function** | Verifies the user's input, ensuring that it is safe to use. | -| **Responsibilities** | β€’ Receives a user's ZKPoK of their inputs.
β€’ Verifies said ZK proofs.
β€’ Generates a signature, allowing the user to use these inputs in a smart contract function call.
β€’ Stores inputs and their proofs in GCS public bucket.
β€’ Communicates directly with FheOS. | +| **Responsibilities** | β€’ Receives users' ZKPoKs for their inputs.
β€’ Verifies said ZK proofs.
β€’ Signs an approval the user passes with the inputs to the contract.
β€’ Stores the verified ciphertext bytes. | -## ZKPoK - Why? +## Why ZKPoK? **Zero-Knowledge Proof of Knowledge (ZKPoK)** provides a crucial security mechanism in CoFHE. It allows users to prove they know the plaintext of an encrypted input they're sending to a smart contract, without revealing the plaintext itself. ZKPoKs protect against potential malicious vectors, including: -1. **Malleability Attacks**: Without ZKPoK protection, attackers could manipulate encrypted data by applying transformations to observed ciphertexts, even without knowing what's inside them. For example, they might combine existing ciphertexts with encrypted zero values to create new valid-looking encrypted data, potentially compromising user's confidentiality. +1. **Malleability attacks**: Without ZKPoK protection, attackers could transform observed ciphertexts into new valid-looking ones without knowing their contents, for example by combining them with encrypted zeros. -2. **Chosen Ciphertext Attacks (CCAs)**: Attackers can submit modified ciphertexts to the system and observe the results, potentially exploiting homomorphic operations to infer sensitive information, manipulate data, or even recover the secret key. +2. **Chosen ciphertext attacks (CCAs)**: Attackers submit modified ciphertexts and observe the results, potentially exploiting homomorphic operations to infer sensitive information or even recover the secret key. -Requiring a ZKPoK for each encrypted input helps running an encryption system in the public space that is a blockchain runtime. It ensures that only users with knowledge of the original plaintext can produce valid proofs. This approach eliminates multiple security risks, protecting sensitive user data and maintaining the system's integrity. +Requiring a ZKPoK for each encrypted input is what makes it safe to run an encryption system in a public runtime like a blockchain. It ensures that only users with knowledge of the original plaintext can produce valid proofs. This eliminates multiple security risks, protecting sensitive user data and maintaining the system's integrity. ## Sending encrypted inputs -As mentioned before, when providing ciphertexts as an input to a smart contract, users have to generate a ZKPoK and get a verification approval first. Although most of the work will be handled by the Client SDK (`@cofhe/sdk`) and FHE.sol, we will describe this mechanism in high-level (also in the diagram below). +When providing ciphertexts as an input to a smart contract, users have to generate a ZKPoK and get a verification approval first. The Client SDK (`@cofhe/sdk`) and `FHE.sol` handle most of this work; the mechanism is described here end to end (also in the diagram below). ZK Proof of Knowledge Flow -The process of sending input(s) to a Smart Contract: +The process of sending inputs to a smart contract: -1. User encrypts an input(s) and generate a ZK proof of knowledge for it. -2. User sends the ciphertext(s) and proof(s) to the ZKVerifier. -3. ZK-Verifier verifies the proof. If valid, sign a message that approves input(s). -4. ZK-Verifier returns the signed approval to User. -5. User sends `(ciphertext, signed_approve)` (one or more) as input(s) to a contract call. -6. Contract verifies the signed message, approving the input(s). -7. Contract performs actual logic. +1. The user encrypts the inputs and generates a ZK proof of knowledge for them. +2. The user sends the ciphertexts and proofs to the ZK Verifier. +3. The ZK Verifier verifies each proof. If valid, it signs a message that approves the input. +4. The ZK Verifier returns the signed approval to the user. +5. The user sends `(ciphertext, signed_approve)` pairs as inputs to a contract call. +6. The contract verifies the signed message, approving the inputs. This also emits `InputVerified`, which anchors a commitment for the input so it becomes decryptable later. +7. The contract performs the actual logic. -As mentioned, most of this process is abstracted away. In fact, steps 1-6 are all handled behind the scenes, while step 7 (the actual logic) is, of course, up to the user to write. +Most of this process is abstracted away. Steps 1 to 6 all happen behind the SDK and library calls, while step 7 (the actual logic) is up to you to write. -## ZK-Verifier +## Trust model -The ZK-Verifier is a zk-verification program. It has two purposes: +The ZK Verifier runs inside a hardware-attested TEE (Intel TDX). Its signing key is released only to the exact attested code image, so neither the operator nor anyone else can sign approvals outside the reviewed program. After a successful verification, the service stores the ciphertext bytes in the coprocessor's ciphertext store and archives the inputs and proofs for auditability. -1. Verify the ZKPoK's of ciphertexts that are intended to be inputted to a CoFHE smart contract. -2. Sign a verification message, allowing the said contract to ensure that the inputs are safe and were validated. +The signed message is verified onchain by the TaskManager using `ecrecover`; the verifier's signer address is registered there as `verifierSigner`. -The signed message that the ZK-Verifier outputs will then be verified by the receiving contract using `ecrecover`. That means that the ZKVerifier's public key will be predetermined and well-known. +## Signature format -The ZKVerifier is intended to run in a TEE to reduce trust and ensure the integrity of the inputs and signed verification messages. +For developers integrating without the SDK, the signed pre-image is: +```text +message_to_sign = keccak256( + ct_hash (32 bytes) || ct_type (1 byte) || security_zone (1 byte) + || account_addr (bytes) || chain_id (32 bytes, big-endian) +) +``` + +The `recid` value the service returns (0 or 1) must be adjusted to 27 or 28 for Solidity's `ecrecover`. From 9d6ace0bd0c424e1ed4148dc45ebfd4e8b214bc5 Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:29:38 +0300 Subject: [PATCH 13/58] [DOCS] deep-dive/slim-listener: two-flow relay model with queues and per-chain instances --- deep-dive/cofhe-components/slim-listener.mdx | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/deep-dive/cofhe-components/slim-listener.mdx b/deep-dive/cofhe-components/slim-listener.mdx index b355e49..c5ab62f 100644 --- a/deep-dive/cofhe-components/slim-listener.mdx +++ b/deep-dive/cofhe-components/slim-listener.mdx @@ -1,12 +1,19 @@ --- title: Slim Listener -description: "Off-chain service that monitors blockchain events and forwards FHE operation requests to the computation layer" +description: "Offchain service that watches TaskManager events on each host chain and relays them into the coprocessor's queues" --- | Aspect | Description | |--------|-------------| -| **Type** | Off-chain event monitoring service | -| **Function** | Listens to blockchain events and forwards FHE operation requests to the fheOS server | -| **Responsibilities** | β€’ Monitors events emitted by the Task Manager contract on the destination chain
β€’ Processes incoming requests and forwards them to the fheOS server
β€’ Ensures reliable delivery of operation requests to the computation layer | +| **Type** | Offchain event relay service. | +| **Function** | Watches TaskManager events on a host chain and publishes them to the coprocessor's queues. | +| **Responsibilities** | β€’ Monitors events emitted by the TaskManager contract on its host chain
β€’ Relays FHE operation events for execution
β€’ Relays verified-input events for commitment posting | -The Slim Listener acts as the bridge between on-chain events and the off-chain computation layer, ensuring that all FHE operation requests are captured and forwarded for processing. +The Slim Listener is the bridge between onchain events and the offchain services. One instance runs per host chain per flow, and each instance does one narrow job: + +| Flow | Watches | Publishes to | Purpose | +|------|---------|--------------|---------| +| FHE operations | `TaskCreated` | `blockchain-events` queue | Feeds the [FheOS Server](/deep-dive/cofhe-components/fheos-server) with work to validate and route. | +| Verified inputs | `InputVerified` | `commitment-requests` queue | Anchors a commitment for every verified input, so [Teecryptor](/deep-dive/cofhe-components/teecryptor) can later decrypt it. | + +Delivery is reliable by construction. The listener publishes with confirms and tracks the last processed block, so a crash or a missed range is re-scanned rather than skipped. From 5a53c6ef50b4fb31885eda650d168ae66d9bf398 Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:29:38 +0300 Subject: [PATCH 14/58] [DOCS] deep-dive/plaintext-storage: describe the publish-then-read result store, drop caching framing --- deep-dive/cofhe-components/plaintext-storage.mdx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/deep-dive/cofhe-components/plaintext-storage.mdx b/deep-dive/cofhe-components/plaintext-storage.mdx index d1d7176..2c53bf0 100644 --- a/deep-dive/cofhe-components/plaintext-storage.mdx +++ b/deep-dive/cofhe-components/plaintext-storage.mdx @@ -1,11 +1,14 @@ --- title: Plaintexts Storage -description: "Internal smart contract that manages storage and retrieval of plaintext values in the host chain with caching mechanisms" +description: "Host-chain contract that stores published decryption results so contracts can read them synchronously" --- | Aspect | Description | |--------|-------------| -| **Type** | Internal Smart Contract | -| **Function** | Storage and management of plaintext values in the host chain | -| **Responsibilities** | β€’ Manages the storage and retrieval of plaintext values in the system
β€’ Provides caching mechanism for plaintext values to improve retrieval performance
β€’ Ensures secure handling of decrypted data within the CoFHE ecosystem | +| **Type** | Internal smart contract on the host chain. | +| **Function** | Stores published decryption results for synchronous reads. | +| **Responsibilities** | β€’ Holds the plaintext result for every published decryption
β€’ Serves reads through the TaskManager's result getters | +Decryption happens offchain, but contracts need the result onchain. When a signed decrypt result is published through `FHE.publishDecryptResult`, the [TaskManager](/deep-dive/cofhe-components/task-manager) verifies the signature and writes the plaintext here. Only the TaskManager can write to this contract. + +Contracts read results back with `FHE.getDecryptResult(handle)`, which reverts if the result is not yet published, or `FHE.getDecryptResultSafe(handle)`, which returns a ready flag instead. See the [Decryption Request Flow](/deep-dive/data-flows/decryption-request-flow) for the full path. From 0914e3c9fd3d9eb9d619694248b83ac2897c5826 Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:30:47 +0300 Subject: [PATCH 15/58] [DOCS] deep-dive: retire threshold-network, result-processor and ct-registry pages with redirects, add teecryptor to nav --- deep-dive/cofhe-components/ct-registry.mdx | 13 ---- .../cofhe-components/result-processor.mdx | 12 --- .../cofhe-components/threshold-network.mdx | 74 ------------------- docs.json | 16 +++- 4 files changed, 13 insertions(+), 102 deletions(-) delete mode 100644 deep-dive/cofhe-components/ct-registry.mdx delete mode 100644 deep-dive/cofhe-components/result-processor.mdx delete mode 100644 deep-dive/cofhe-components/threshold-network.mdx diff --git a/deep-dive/cofhe-components/ct-registry.mdx b/deep-dive/cofhe-components/ct-registry.mdx deleted file mode 100644 index 74e0721..0000000 --- a/deep-dive/cofhe-components/ct-registry.mdx +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: CTRegistry -description: "Registry contract that manages the mapping between temporary ciphertext hashes and their actual hash values, ensuring secure lookup and verification" ---- - -| Aspect | Description | -|--------|-------------| -| **Type** | Registry Contract | -| **Function** | Manages the mapping between temporary ciphertext hashes and their actual hash values | -| **Responsibilities** | β€’ Maintains a consistent record of ciphertext identifiers throughout the CoFHE lifecycle
β€’ Enables secure lookup of final ciphertexts using their temporary handles
β€’ Restricts read/write access to ensure integrity and prevent unauthorized updates | - -The CTRegistry acts as a source of truth for encrypted data identifiers, mapping temporary hashes to their final computed values. This ensures results from off-chain computation can be securely resolved and verified by their originating requests. - diff --git a/deep-dive/cofhe-components/result-processor.mdx b/deep-dive/cofhe-components/result-processor.mdx deleted file mode 100644 index cc97a29..0000000 --- a/deep-dive/cofhe-components/result-processor.mdx +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Result Processor -description: "Off-chain service that handles FHE operation results and publishes them back to the blockchain" ---- - -| Aspect | Description | -|--------|-------------| -| **Type** | Off-chain result handling service | -| **Function** | Receives computation results from fheOS and publishes them to the blockchain | -| **Responsibilities** | β€’ Receives FHE operation results from the fheOS server
β€’ Sends results to the Data Availability layer
β€’ Publishes decryption results back to the Task Manager on the host chain | - -The Result Processor ensures that computation results from the off-chain fheOS server are properly relayed back to the blockchain, completing the FHE operation lifecycle. diff --git a/deep-dive/cofhe-components/threshold-network.mdx b/deep-dive/cofhe-components/threshold-network.mdx deleted file mode 100644 index 6af3220..0000000 --- a/deep-dive/cofhe-components/threshold-network.mdx +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: Threshold Network -description: "Off-chain distributed network that processes and executes decryption requests using Multi-Party Computation (MPC) protocols" ---- - -| Aspect | Description | -| -------------------- | --------------------------------------------------------------------------------------------------------------------------------- | -| **Type** | Offchain, distributed network. | -| **Function** | Process and execute decryption requests. | -| **Responsibilities** | β€’ Gets ciphertext decryption requests
β€’ Authenticates and validates them
β€’ Runs an MPC protocol to decrypt the ciphertext | - -In any system utilizing encryption, a crucial step is the eventual decryption of data. For example, if we were to build a privacy-preserving ERC20 contract, users would ultimately need to access their encrypted balances. In the case of CoFHE, this decryption process is managed by the Threshold Network. - -## Motivation - -The Threshold Network is a component of a complex cryptographic system with the sole purpose of enhancing the security and trustworthiness of the system by distributing control of the decryption process. Rather than having a single secret key stored and used for the decryption by a centralized entity, we distribute secret shares (to hide the original decryption key) among multiple parties. This enforces collaboration among parties in order to decrypt; the parties perform an MPC (Multi-Party Computation) protocol that results in the decrypted value of a given ciphertext block (single ciphertext can contain a multiple of these so called blocks), ensuring that no information about the full secret key is leaked at any time. - -A practical example of a threshold network in practice is vote counting. Multiple representatives of competing parties gather around to count votes from recent elections. In order to attempt voter fraud all of the participating parties would have to collaborate (which is unlikely). Threshold Network is built on the exact same principle. - -## Concept - -Threshold Network performs decryption operations. The Threshold Network is currently initialized by a Trusted Dealer (in the future, we plan to eliminate the Trusted Dealer). The Dealer initially generates a key. The Trusted Dealer uses the private key within a secret-sharing algorithm to generate secret shares to share among individual members. Each member holds exactly one secret share. To perform a decryption, the secret shares are used to perform partial decryptions through a multiparty computation (MPC) protocol. These partial decryptions are then combined into the final plaintext. The protocol requires cooperation from all participants to perform a decryption, ensuring no single entity can decrypt the ciphertext alone. This distributed control mechanism enhances security by preventing unilateral access to encrypted data. - -## Decryption Process - -The Threshold network includes three main components: - -- **Coordinator** - coordinates communication between the party members to perform the MPC protocol. -- **Party Members** - the individual parties that hold a secret share and execute the MPC protocol. -- **Trusted Dealer** - responsible for initializing the protocol, and for providing random data to the party members, needed to perform the protocol securely. - - -Threshold Network Flow - - -All incoming decryption requests reach the Coordinator (1). - -The coordinator splits the CT into individual Learning With Errors (LWE) CT blocks. These blocks then get broadcast to partymembers (2). During this process data is exchanged back and forth until the decryption of all blocks is complete upon which the coordinator reassembles the plaintext from decrypted LWE CT blocks. The plaintext value then gets sent back to the user. - -The MPC protocol consists of multiple stages. In each stage, a partymember performs a calculation on a received input and returns the result (a.k.a. intermediate result) to the Coordinator. Each intermediate result gets sent back to the coordinator in order to get distributed among other partymembers as an input for the next stage. - -## Dispatcher Signing - -The Threshold Network's **Dispatcher** component signs every decrypt and sealoutput result with an ECDSA key. This signature enables on-chain verification β€” clients can publish signed decrypt results directly to the TaskManager contract via `FHE.publishDecryptResult()`. - -### Signed Message Format - -For decrypt results, the Dispatcher produces a fixed **76-byte** message before signing: - -| Field | Size | Encoding | -|-------|------|----------| -| `result` | 32 bytes | uint256, big-endian, left-padded with zeros | -| `enc_type` | 4 bytes | i32, big-endian | -| `chain_id` | 8 bytes | u64, big-endian | -| `ct_hash` | 32 bytes | uint256, big-endian | - -This format is aligned with Solidity types so the TaskManager can reconstruct and verify the same hash on-chain using `_computeDecryptResultHash`. - -### Signature V Format - -The ECDSA recovery ID (`v` value) can be returned in two formats, controlled by the HTTP header `X-Signature-V-Format`: - -| Header Value | V Format | Use Case | -|-------------|----------|----------| -| `"raw"` (default) | 0-3 | General purpose, k256 native | -| `"evm"` | 27-28 | Direct use with Solidity's `ecrecover` / OpenZeppelin `ECDSA.recover` | - - -For on-chain verification via `FHE.publishDecryptResult()`, use `"evm"` format so the signature is directly compatible with the TaskManager's ECDSA verification. - - -### Signer Registration - -The Dispatcher's signing key address is registered on-chain as `decryptResultSigner` in the TaskManager contract. Only results signed by this address are accepted. Setting it to `address(0)` disables verification (debug mode only). diff --git a/docs.json b/docs.json index a03f619..22a17cf 100644 --- a/docs.json +++ b/docs.json @@ -239,14 +239,12 @@ "deep-dive/cofhe-components/task-manager", "deep-dive/cofhe-components/acl", "deep-dive/cofhe-components/slim-listener", - "deep-dive/cofhe-components/result-processor", "deep-dive/cofhe-components/plaintext-storage", - "deep-dive/cofhe-components/ct-registry", "deep-dive/cofhe-components/commitment-registry", "deep-dive/cofhe-components/zk-verifier", "deep-dive/cofhe-components/fheos-server", "deep-dive/cofhe-components/fhe-engine", - "deep-dive/cofhe-components/threshold-network" + "deep-dive/cofhe-components/teecryptor" ] }, { @@ -310,6 +308,18 @@ { "source": "/client-sdk/guides/permits", "destination": "/client-sdk/guides/acps" + }, + { + "source": "/deep-dive/cofhe-components/threshold-network", + "destination": "/deep-dive/cofhe-components/teecryptor" + }, + { + "source": "/deep-dive/cofhe-components/result-processor", + "destination": "/deep-dive/cofhe-components/fhe-engine" + }, + { + "source": "/deep-dive/cofhe-components/ct-registry", + "destination": "/deep-dive/cofhe-components/commitment-registry" } ], "integrations": { From 00f494407ed4ca4a2c7af4434d24c9092c41d929 Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:32:30 +0300 Subject: [PATCH 16/58] [DOCS] deep-dive/future-plans: trust points rewritten around the TEE architecture, feature statuses updated --- deep-dive/research/future-plans.mdx | 79 ++++++++++++++--------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/deep-dive/research/future-plans.mdx b/deep-dive/research/future-plans.mdx index af70af2..90367e8 100644 --- a/deep-dive/research/future-plans.mdx +++ b/deep-dive/research/future-plans.mdx @@ -3,44 +3,43 @@ title: Future Plans sidebar_position: 9 description: "Roadmap for CoFHE decentralization, upcoming features, and planned improvements" --- -Future Plans - -## Road to Decentralization - -Integrating FHE into a blockchain-runtime is a hard and complex task. Our engineering philosophy is _Ship Fast_, and we believe that to build the best possible product we need to meet real users early. Similar to the approach described in [Vitalik's "training wheels" post](https://ethereum-magicians.org/t/proposed-milestones-for-rollups-taking-off-training-wheels/11571) (in the context of rollups), we too are relying on "training wheels" releasing CoFHE to achieve this goal. - -Outlined here is a non-exhaustive list of trust-points, centralized components and compromises made to ship CoFHE to users as fast as possible, along with how we plan to address them in the future. This list will be updated as things progress. - -| Component | Compromise | Plan to solve | Timeline | Status | -| ---------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------- | -------- | ------ | -| Threshold Network (TN) | All parties are run by Fhenix | N/A | N/A | ❌ | -| Threshold Network (TN) | Use of a Trusted Dealer for keys and random data generation | N/A | N/A | ❌ | -| Threshold Network (TN) | Parties trust the Coordinator | N/A | N/A | ❌ | -| Threshold Network (TN) | TN trusts CoFHE (tx-flow decryptions) | N/A | N/A | ❌ | -| Threshold Network (TN) | Parties trust a Trusted Dealer | 1. Run TD in a TEE
2. Public ceremony for share creation
3. Eliminate TD | N/A | ❌ | -| Threshold Network (TN) | Parties are not using unique random data within the protocol | Pull random data from the TD | N/A | ❌ | -| Threshold Network (TN) | SealOutput reencryption performed in a centralized manner | N/A | N/A | ❌ | -| ZK-Verifier (ZKV) | CoFHE trusts ZK-Verifier | Run ZKV in a TEE | N/A | ❌ | -| CoFHE | Trust in CoFHE to perform correct FHE computations | External verification using AVS | N/A | ❌ | -| CoFHE | User inputs stored in a centralized manner | Use a decentralized DA | N/A | ❌ | -| All | Codebase is unaudited | Perform a security audit | N/A | ❌ | -| All | Codebase is not fully open-source | Open-source codebase | N/A | ❌ | - -## Upcoming Features - -In the spirit of transparency, here we describe the general feature-roadmap planned for CoFHE. This list will be updated as things progress. - -| Feature | Type | Description | Timeline | Status | -| ------------------------------ | ------------------- | -------------------------------------------------------------------------------- | -------- | ------ | -| Integration SDK | DevX | SDK to easily integrate CoFHE-specific components into dApps | N/A | ❌ | -| Additional external devtools | DevX | Remix, Alchemy SDK and more | N/A | ❌ | -| RNG | DevX | Ability to generate secure randomness in contracts | N/A | ❌ | -| Alternative runtimes | DevX | Support for additional runtimes other than EVM | N/A | ❌ | -| FHE ops in view functions | DevX | Ability to execute FHE operations in view functions in contracts | N/A | ❌ | -| GPU support | UX | Run FHE operations on a GPU backend, improving performance and overall latency | N/A | ❌ | -| FPGA support | UX | Run FHE operations on an FPGA backend, improving performance and overall latency | N/A | ❌ | -| T-out-of-N MPC protocol | Robustness | Improve robustness of the TN by not requiring all parties to be online | N/A | ❌ | -| Support additional host-chains | DevX/UX | N/A | N/A | ❌ | -| Key shares rotation | Robustness/Security | Ability to rotate the party shares in the TN | N/A | ❌ | -| Key Rotation | Robustness/Security | Ability to rotate the key for the entire protocol | N/A | ❌ | +## Road to decentralization + +Integrating FHE into a blockchain runtime is a hard and complex task. Our engineering philosophy is to ship fast: to build the best possible product we need to meet real users early. Similar to the approach described in [Vitalik's "training wheels" post](https://ethereum-magicians.org/t/proposed-milestones-for-rollups-taking-off-training-wheels/11571) (in the context of rollups), CoFHE ships with training wheels of its own. + +Outlined here is a non-exhaustive list of trust points, centralized components, and compromises made to ship CoFHE to users as fast as possible. Each row notes how we plan to address it, and the list will be updated as things progress. + +| Component | Compromise | Plan to solve | Status | +| --- | --- | --- | --- | +| Teecryptor | Decryption is served by a single TEE service operated by Fhenix | Replace with the Threshold Network (below) | Planned | +| Teecryptor | Trust in the TEE hardware vendor and its attestation chain | Threshold decryption removes the hardware trust anchor | Planned | +| Key custody | The FHE key is reconstructed inside one attested enclave at runtime | Threshold decryption, where no party ever holds the full key | Planned | +| CoFHE | Trust in CoFHE to perform correct FHE computations | External verification | Planned | +| CoFHE | User inputs stored in a centralized manner | Use a decentralized DA | Planned | +| All | Codebase is unaudited | Perform a security audit | Planned | +| All | Codebase is not fully open source | Open-source the codebase | Planned | + +One earlier training wheel has already been removed: the ZK Verifier now runs inside a hardware-attested TEE, with its signing key released only to the attested code image. + +## The path to the Threshold Network + +The end state for decryption is a Threshold Network. Independent parties decrypt through multi-party computation, so no single party (and no single machine) ever holds the FHE key. It will replace [Teecryptor](/deep-dive/cofhe-components/teecryptor) and remove the trust points listed above in one move. Robustness goals for it include a t-out-of-n protocol (no requirement that every party stays online), party share rotation, and full protocol key rotation. + +See [Research in Fhenix](/deep-dive/research/research-in-fhenix) for the threshold decryption protocol behind this plan. + +## Upcoming features + +In the spirit of transparency, here is the general feature roadmap planned for CoFHE. + +| Feature | Type | Description | Status | +| --- | --- | --- | --- | +| RNG | DevX | Secure randomness in contracts (`FHE.random`) | Shipped | +| Additional host chains | DevX/UX | Multiple EVM host chains (three run on the current testnet) | Shipped, more planned | +| Hardhat and Foundry plugins | DevX | First-party tooling for the standard EVM dev stacks | Shipped | +| React SDK | DevX | `@cofhe/react` hooks and components for dApp frontends | Shipped | +| Additional external devtools | DevX | Remix, Alchemy SDK and more | Planned | +| GPU support | UX | Run FHE operations on a GPU backend for lower latency | In progress | +| FPGA support | UX | Run FHE operations on an FPGA backend | Planned | +| FHE ops in view functions | DevX | Execute FHE operations in contract view functions | Planned | +| Alternative runtimes | DevX | Support for runtimes other than the EVM | Planned | From 75a97a1038e7cebb718961b39b5b6609c34e6ecf Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:32:30 +0300 Subject: [PATCH 17/58] [DOCS] deep-dive/research-in-fhenix: position threshold decryption as the successor to the TEE path --- deep-dive/research/research-in-fhenix.mdx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/deep-dive/research/research-in-fhenix.mdx b/deep-dive/research/research-in-fhenix.mdx index c92bb86..3978c31 100644 --- a/deep-dive/research/research-in-fhenix.mdx +++ b/deep-dive/research/research-in-fhenix.mdx @@ -4,11 +4,10 @@ sidebar_position: 10 description: "Research into novel cryptographic techniques and optimization of Fully Homomorphic Encryption for blockchain applications" --- -# Research in Fhenix +Our research explores novel cryptographic techniques to push the boundaries of Fully Homomorphic Encryption (FHE). We mainly work on optimizing the latency of FHE-based smart contracts using the latest published schemes, keeping them both efficient and secure. Ultimately, the aim is to broaden the practical viability of FHE by delivering protocols that meet real-world performance needs. -Our research explores novel cryptographic techniques to push the boundaries of Fully Homomorphic Encryption (FHE). We mainly delve into optimizing the latency of FHE-based smart contracts using state-of-the-art schemes, ensuring they remain both efficient and secure. Ultimately, our aim is to broaden the practical viability of FHE by delivering protocols that meet real-world performance needs. We also designed a secure high performance threshold decryption protocol (see below). +## Threshold decryption for FHE -## Current Project: Threshold Decryption for FHE - -We designed a new threshold FHE decryption protocol that achieves both **unprecedented throughput** and **shortest latency** compared to existing solutions. Specifically, it improves **throughput by ~20,000Γ—** and **cuts latency by up to 37Γ—** relative to the state of the art. This is achieved by securely removing ciphertext noise with an efficient MPC-based approach, eliminating the need for noise flooding while maintaining strong simulation-based security. +Decryption in CoFHE is currently served by [Teecryptor](/deep-dive/cofhe-components/teecryptor), a TEE-based service. The research below is the path to its planned decentralized successor, the [Threshold Network](/deep-dive/research/future-plans). +We designed a new threshold FHE decryption protocol that improves throughput by roughly 20,000x and cuts latency by up to 37x relative to the prior state of the art. This is achieved by securely removing ciphertext noise with an efficient MPC-based approach, eliminating the need for noise flooding while maintaining strong simulation-based security. From ed578d103b45c3089372346b59d9db548a7a6eb4 Mon Sep 17 00:00:00 2001 From: haim Date: Wed, 19 Aug 2026 23:33:28 +0300 Subject: [PATCH 18/58] [DOCS] deep-dive: fix internal links to fhe-engine and off-chain-decryption-flow --- deep-dive/cofhe-components/overview.mdx | 2 +- deep-dive/data-flows/decryption-request-flow.mdx | 2 +- deep-dive/data-flows/fhe-operation-request-flow.mdx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index c8b4fdf..c981156 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -60,7 +60,7 @@ flowchart LR - **[ZK Verifier](/deep-dive/cofhe-components/zk-verifier)**: verifies the zero-knowledge proof attached to every encrypted input, signs it, and stores the ciphertext bytes. - **[Slim Listener](/deep-dive/cofhe-components/slim-listener)**: watches TaskManager events on each host chain and forwards them into the coprocessor's queues. - **[FheOS Server](/deep-dive/cofhe-components/fheos-server)**: ingests task events, verifies inputs, creates result placeholders, and routes work to the FHE Engine. It does not execute FHE operations itself. -- **[FHE Engine](/deep-dive/cofhe-components/fheos-server)**: executes every FHE operation on encrypted data, persists the resulting ciphertexts, and emits a commitment for each result. +- **[FHE Engine](/deep-dive/cofhe-components/fhe-engine)**: executes every FHE operation on encrypted data, persists the resulting ciphertexts, and emits a commitment for each result. - **Ciphertext Server**: stores and serves ciphertext bytes to the other services. - **Blockchain Poster**: batches result commitments and posts them to the CommitmentRegistry. - **[Teecryptor](/deep-dive/cofhe-components/teecryptor)**: the decryption service. It runs inside a hardware-attested TEE, authorizes every request against the onchain ACL, verifies the ciphertext commitment, and returns signed or sealed results. diff --git a/deep-dive/data-flows/decryption-request-flow.mdx b/deep-dive/data-flows/decryption-request-flow.mdx index 9a5b940..c84e145 100644 --- a/deep-dive/data-flows/decryption-request-flow.mdx +++ b/deep-dive/data-flows/decryption-request-flow.mdx @@ -13,7 +13,7 @@ This page follows a plaintext all the way onto the chain: from the SDK's `decryp There are two SDK entry points: - **`decryptForTx`**: returns the plaintext with a signature you can publish onchain. This page covers it. -- **`decryptForView`**: returns a sealed result only the permit holder can read, for UI display. Covered in the [Offchain Decryption Flow](/deep-dive/data-flows/offchain-decryption-flow). +- **`decryptForView`**: returns a sealed result only the permit holder can read, for UI display. Covered in the [Offchain Decryption Flow](/deep-dive/data-flows/off-chain-decryption-flow). ## Step-by-step flow diff --git a/deep-dive/data-flows/fhe-operation-request-flow.mdx b/deep-dive/data-flows/fhe-operation-request-flow.mdx index aed4efd..1fea64f 100644 --- a/deep-dive/data-flows/fhe-operation-request-flow.mdx +++ b/deep-dive/data-flows/fhe-operation-request-flow.mdx @@ -15,7 +15,7 @@ This page follows a single FHE operation from the contract call that requests it | **[TaskManager](/deep-dive/cofhe-components/task-manager)** | Validates requests, checks the [ACL](/deep-dive/cofhe-components/acl), and emits task events | | **[Slim Listener](/deep-dive/cofhe-components/slim-listener)** | Watches TaskManager events on each host chain and enqueues them | | **[FheOS Server](/deep-dive/cofhe-components/fheos-server)** | Ingests task events, validates them, and routes work to the FHE Engine | -| **[FHE Engine](/deep-dive/cofhe-components/fheos-server)** | Executes the FHE operation and stores the result ciphertext | +| **[FHE Engine](/deep-dive/cofhe-components/fhe-engine)** | Executes the FHE operation and stores the result ciphertext | | **Blockchain Poster** | Batches result commitments and posts them onchain | | **[CommitmentRegistry](/deep-dive/cofhe-components/commitment-registry)** | Records a hash commitment for every result ciphertext | From afa14d8b88c4a281d660377489da5909b8da800e Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 23 Aug 2026 17:17:20 +0300 Subject: [PATCH 19/58] [DOCS] deep-dive: Mermaid house theme matching the diagram design system, stamped by scripts/sync-mermaid-theme.py --- .../cofhe-components/commitment-registry.mdx | 1 + deep-dive/cofhe-components/overview.mdx | 1 + deep-dive/cofhe-components/teecryptor.mdx | 3 +- .../data-flows/decryption-request-flow.mdx | 1 + .../data-flows/encryption-request-flow.mdx | 3 +- .../data-flows/fhe-operation-request-flow.mdx | 1 + .../data-flows/off-chain-decryption-flow.mdx | 1 + scripts/mermaid-theme.json | 38 +++++++++++ scripts/sync-mermaid-theme.py | 64 +++++++++++++++++++ 9 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 scripts/mermaid-theme.json create mode 100644 scripts/sync-mermaid-theme.py diff --git a/deep-dive/cofhe-components/commitment-registry.mdx b/deep-dive/cofhe-components/commitment-registry.mdx index 73a22bf..1a6996f 100644 --- a/deep-dive/cofhe-components/commitment-registry.mdx +++ b/deep-dive/cofhe-components/commitment-registry.mdx @@ -30,6 +30,7 @@ mapping(address => bool) poster `version` is an opaque `bytes32` tag chosen by the coprocessor when FHE parameters change, currently the ASCII tag `"2"` (see [the FHE Engine `COMMITMENT_VERSION` notes](https://github.com/FhenixProtocol/cofhe/blob/master/CHANGELOG.md#060---2026-05-05)). Every version moves through a small state machine: ```mermaid +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% stateDiagram-v2 Unset --> Active Active --> Deprecated diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index c981156..fb6995d 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -6,6 +6,7 @@ description: "How CoFHE's onchain contracts and offchain services fit together t CoFHE (Coprocessor for Fully Homomorphic Encryption) lets smart contracts compute on encrypted data. Contracts request operations through onchain calls; a set of offchain services executes them and commits to the results. Data stays encrypted through the entire lifecycle, and every result can be verified against an onchain commitment. ```mermaid +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% flowchart LR subgraph App["Application"] SDK["Client SDK"] diff --git a/deep-dive/cofhe-components/teecryptor.mdx b/deep-dive/cofhe-components/teecryptor.mdx index e36dfa9..2325fed 100644 --- a/deep-dive/cofhe-components/teecryptor.mdx +++ b/deep-dive/cofhe-components/teecryptor.mdx @@ -44,10 +44,11 @@ A handle whose ciphertext or commitment has not landed yet is not an error. Teec ```mermaid +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% sequenceDiagram participant SDK as Client SDK participant Teecryptor - participant TaskManager as TaskManager (host chain) + participant TaskManager participant Registry as CommitmentRegistry participant Store as Ciphertext store diff --git a/deep-dive/data-flows/decryption-request-flow.mdx b/deep-dive/data-flows/decryption-request-flow.mdx index c84e145..04151c8 100644 --- a/deep-dive/data-flows/decryption-request-flow.mdx +++ b/deep-dive/data-flows/decryption-request-flow.mdx @@ -76,6 +76,7 @@ To check a signature without storing the result, use the `verifyDecryptResult` f ## Flow diagram ```mermaid +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% sequenceDiagram participant User participant SDK as Client SDK diff --git a/deep-dive/data-flows/encryption-request-flow.mdx b/deep-dive/data-flows/encryption-request-flow.mdx index af3fbf3..313b550 100644 --- a/deep-dive/data-flows/encryption-request-flow.mdx +++ b/deep-dive/data-flows/encryption-request-flow.mdx @@ -18,12 +18,13 @@ This page follows an encrypted input from the plaintext in your application to a ## Flow diagram ```mermaid +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% sequenceDiagram participant App as Your app participant SDK as Client SDK participant ZK as ZK Verifier participant CTS as Ciphertext Server - participant TM as TaskManager (host chain) + participant TM as TaskManager App->>SDK: encryptInputs([...]).execute() SDK->>SDK: encrypt with TFHE, generate zkPoK diff --git a/deep-dive/data-flows/fhe-operation-request-flow.mdx b/deep-dive/data-flows/fhe-operation-request-flow.mdx index 1fea64f..1a658a6 100644 --- a/deep-dive/data-flows/fhe-operation-request-flow.mdx +++ b/deep-dive/data-flows/fhe-operation-request-flow.mdx @@ -22,6 +22,7 @@ This page follows a single FHE operation from the contract call that requests it ## Flow diagram ```mermaid +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% sequenceDiagram participant Contract as Your contract (FHE.sol) participant TM as TaskManager diff --git a/deep-dive/data-flows/off-chain-decryption-flow.mdx b/deep-dive/data-flows/off-chain-decryption-flow.mdx index 2a17a95..4d05a1f 100644 --- a/deep-dive/data-flows/off-chain-decryption-flow.mdx +++ b/deep-dive/data-flows/off-chain-decryption-flow.mdx @@ -161,6 +161,7 @@ Behind the scenes: ## Flow diagram ```mermaid +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% sequenceDiagram participant App as Your app participant SDK as Client SDK diff --git a/scripts/mermaid-theme.json b/scripts/mermaid-theme.json new file mode 100644 index 0000000..ab4246e --- /dev/null +++ b/scripts/mermaid-theme.json @@ -0,0 +1,38 @@ +{ + "theme": "base", + "themeVariables": { + "fontFamily": "Menlo, Monaco, Consolas, monospace", + "fontSize": "13px", + "primaryColor": "#8FBAF5", + "primaryBorderColor": "#2E7CF6", + "primaryTextColor": "#0A1626", + "lineColor": "#4C8DFF", + "signalColor": "#4C8DFF", + "signalTextColor": "#8FA3BF", + "actorBkg": "#8FBAF5", + "actorBorder": "#2E7CF6", + "actorTextColor": "#0A1626", + "actorLineColor": "#3D4654", + "noteBkgColor": "#14171C", + "noteBorderColor": "#3D4654", + "noteTextColor": "#AFC3DE", + "activationBkgColor": "#1E3A5F", + "activationBorderColor": "#4C8DFF", + "clusterBkg": "#14171C", + "clusterBorder": "#3D4654", + "titleColor": "#E7EAEE", + "edgeLabelBackground": "#8FBAF5", + "textColor": "#AFC3DE", + "labelTextColor": "#E7EAEE", + "tertiaryColor": "#14171C", + "loopTextColor": "#AFC3DE", + "labelBoxBkgColor": "#1E3A5F", + "labelBoxBorderColor": "#4C8DFF" + }, + "sequence": { + "actorFontFamily": "Menlo, Monaco, Consolas, monospace", + "messageFontFamily": "Menlo, Monaco, Consolas, monospace", + "noteFontFamily": "Menlo, Monaco, Consolas, monospace", + "width": 220 + } +} \ No newline at end of file diff --git a/scripts/sync-mermaid-theme.py b/scripts/sync-mermaid-theme.py new file mode 100644 index 0000000..f253664 --- /dev/null +++ b/scripts/sync-mermaid-theme.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +"""Stamp the shared Mermaid init directive into every mermaid block. + +The house theme lives in scripts/mermaid-theme.json. This script inserts the +matching %%{init: ...}%% directive as the first line of every ```mermaid block +in the docs, replacing any existing init line, so all diagrams share one style +and the theme can be changed in one file. + +Usage: + python3 scripts/sync-mermaid-theme.py # rewrite files in place + python3 scripts/sync-mermaid-theme.py --check # exit 1 if any block is out of date +""" + +import json +import re +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent +THEME_FILE = ROOT / "scripts" / "mermaid-theme.json" +SKIP_DIRS = {"local", "node_modules", ".git", "snippets"} + +BLOCK_RE = re.compile(r"(```mermaid[ \t]*\n)(.*?)(```)", re.DOTALL) +INIT_RE = re.compile(r"^%%\{init:.*\}%%\s*\n", re.DOTALL) + + +def directive() -> str: + theme = json.loads(THEME_FILE.read_text()) + return "%%{init: " + json.dumps(theme, separators=(", ", ": ")) + "}%%\n" + + +def sync_text(text: str, init_line: str) -> str: + def repl(m: re.Match) -> str: + body = INIT_RE.sub("", m.group(2), count=1) + return m.group(1) + init_line + body + m.group(3) + + return BLOCK_RE.sub(repl, text) + + +def main() -> int: + check = "--check" in sys.argv + init_line = directive() + stale = [] + for path in sorted(ROOT.rglob("*.mdx")): + if any(part in SKIP_DIRS for part in path.parts): + continue + original = path.read_text() + updated = sync_text(original, init_line) + if updated != original: + if check: + stale.append(path.relative_to(ROOT)) + else: + path.write_text(updated) + print(f"updated {path.relative_to(ROOT)}") + if check and stale: + for p in stale: + print(f"stale mermaid theme: {p}") + print("Run: python3 scripts/sync-mermaid-theme.py") + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 8216fb0a4deaefe14a3eff7c620fd9da48afb332 Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 23 Aug 2026 17:19:47 +0300 Subject: [PATCH 20/58] [DOCS] deep-dive/decryption-request-flow: merge offchain decryption page into one Decryption Flow, redirect and SDK guide links --- deep-dive/cofhe-components/overview.mdx | 3 +- .../data-flows/decryption-request-flow.mdx | 96 +++++---- .../data-flows/off-chain-decryption-flow.mdx | 194 ------------------ docs.json | 7 +- 4 files changed, 66 insertions(+), 234 deletions(-) delete mode 100644 deep-dive/data-flows/off-chain-decryption-flow.mdx diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index fb6995d..390c59a 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -72,8 +72,7 @@ Services communicate through message queues rather than direct calls, so each st 1. **[Encryption request](/deep-dive/data-flows/encryption-request-flow)**: an input is encrypted client-side and proven valid with a zero-knowledge proof before it enters the chain. 2. **[FHE operation flow](/deep-dive/data-flows/fhe-operation-request-flow)**: a contract requests a computation; the coprocessor executes it and commits to the result. -3. **[Decryption request](/deep-dive/data-flows/decryption-request-flow)**: the SDK asks Teecryptor for a signed plaintext that can be published onchain. -4. **[Offchain decryption](/deep-dive/data-flows/off-chain-decryption-flow)**: the SDK receives the plaintext sealed to a permit, for reads that never touch the chain. +3. **[Decryption](/deep-dive/data-flows/decryption-request-flow)**: the SDK asks Teecryptor to decrypt a handle, either as a signed plaintext for onchain publication or sealed to a permit for offchain reads. ## What comes next diff --git a/deep-dive/data-flows/decryption-request-flow.mdx b/deep-dive/data-flows/decryption-request-flow.mdx index 04151c8..9b7945d 100644 --- a/deep-dive/data-flows/decryption-request-flow.mdx +++ b/deep-dive/data-flows/decryption-request-flow.mdx @@ -1,21 +1,27 @@ --- -title: Decryption Request Flow +title: Decryption Flow sidebar_position: 3 -description: "End-to-end path of a decryption: SDK request, TEE decryption, signed result, onchain publication, contract read-back" +description: "How CoFHE values get decrypted: decryptForTx with onchain publication, decryptForView with sealed output" --- -This page follows a plaintext all the way onto the chain: from the SDK's `decryptForTx` call, through [Teecryptor](/deep-dive/cofhe-components/teecryptor), to a signed result the TaskManager verifies and any contract can read. +Decryption in CoFHE is SDK-driven and happens offchain, inside [Teecryptor](/deep-dive/cofhe-components/teecryptor). A contract's role is to grant access and, when the result should go onchain, to read it back after publication. -**Contracts cannot request decryption onchain.** The TaskManager rejects decrypt tasks (`DecryptFunctionNotSupported`), and `FHE.decrypt` no longer exists in the FHE library. Decryption is exclusively SDK-driven. A contract's role is to grant access (`FHE.allow`, `FHE.allowGlobal`, or `TaskManager.allowForDecryption`) and later read the published result. This design keeps decryption off the transaction path. The coprocessor never pushes plaintexts into your contract; anyone holding a valid signature publishes the result, and the contract verifies that signature itself. +**Contracts cannot request decryption onchain.** The TaskManager rejects decrypt tasks (`DecryptFunctionNotSupported`), and `FHE.decrypt` no longer exists in the FHE library. The coprocessor never pushes plaintexts into your contract. -There are two SDK entry points: +There are two SDK entry points, one per destination: -- **`decryptForTx`**: returns the plaintext with a signature you can publish onchain. This page covers it. -- **`decryptForView`**: returns a sealed result only the permit holder can read, for UI display. Covered in the [Offchain Decryption Flow](/deep-dive/data-flows/off-chain-decryption-flow). +- **`decryptForTx`**: returns the plaintext with a Teecryptor signature you can publish onchain. Guide: [Decrypt to Tx](/client-sdk/guides/decrypt-to-tx). +- **`decryptForView`**: returns the plaintext sealed to your [permit](/client-sdk/guides/permits), for UI display and offchain reads. Guide: [Decrypt to View](/client-sdk/guides/decrypt-to-view). -## Step-by-step flow + +A freshly computed handle may not be decryptable immediately: its ciphertext and commitment land shortly after the transaction. Until then Teecryptor answers with a retryable status and the SDK re-submits automatically. + + +## The shared pipeline + +Both entry points start the same way. @@ -24,7 +30,7 @@ The contract that owns the encrypted value marks the handle decryptable: `FHE.al -The user calls `decryptForTx` with the ciphertext handle: +The application calls one of the two builders: ```typescript const { ctHash, decryptedValue, signature } = await client @@ -33,20 +39,28 @@ const { ctHash, decryptedValue, signature } = await client .execute(); ``` -The request goes to Teecryptor with the handle, the host chain id, and the [permit](/client-sdk/guides/permits). For publicly decryptable handles, use `.withoutPermit()`. +```typescript +const balance = await client + .decryptForView(ctHash, FheTypes.Uint32) + .withPermit() + .execute(); +``` + +The request goes to Teecryptor with the handle, the host chain id, and the permit. For publicly decryptable handles, `decryptForTx` can use `.withoutPermit()` instead. -Teecryptor authorizes the request against the onchain ACL, fetches the ciphertext exactly as stored, verifies it against the onchain commitment, and decrypts it inside the attested TEE. If the ciphertext or its commitment has not landed yet (a freshly computed handle), the SDK retries automatically until it is available. - -See the [Teecryptor page](/deep-dive/cofhe-components/teecryptor) for the full pipeline. +Teecryptor authorizes the request against the onchain ACL, fetches the ciphertext exactly as stored, verifies it against the onchain commitment, and decrypts it inside the attested enclave. See the [Teecryptor page](/deep-dive/cofhe-components/teecryptor) for the full pipeline. - -Teecryptor returns the plaintext together with an ECDSA signature over a fixed 76-byte message (result, encryption type, chain id, ciphertext hash). The signing key lives only inside the enclave, and its address is registered onchain as the TaskManager's `decryptResultSigner`. - + + +From here the two paths diverge. + +## The transaction path + +For `decryptForTx`, Teecryptor returns the plaintext together with an ECDSA signature over a fixed 76-byte message (result, encryption type, chain id, ciphertext hash). The signing key lives only inside the enclave, and its address is registered onchain as the TaskManager's `decryptResultSigner`. - Anyone holding the signature submits it in a transaction: ```solidity @@ -58,9 +72,7 @@ The TaskManager recomputes the message hash, recovers the signer, and rejects an Publication is permissionless: any relayer with a valid signature can deliver the result. `decryptForTx` itself costs no gas; gas is paid only by this publish transaction. - - Once published, any contract reads the plaintext: ```solidity @@ -69,34 +81,46 @@ uint64 value = FHE.getDecryptResult(handle); // reverts if n ``` To check a signature without storing the result, use the `verifyDecryptResult` family on the TaskManager. - - +## The view path + +For `decryptForView`, Teecryptor never returns a bare plaintext. It encrypts the result to the permit's sealing key, and the SDK unseals it locally, so the plaintext is not exposed in transit. There is nothing to publish; the value goes straight to your application. ## Flow diagram ```mermaid %%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% sequenceDiagram - participant User + participant App as Your app participant SDK as Client SDK participant Teecryptor - participant TaskManager - participant Contract as Your contract - - Contract->>TaskManager: FHE.allow / allowGlobal (grant access) - User->>SDK: decryptForTx(ctHash) - SDK->>Teecryptor: decrypt request (handle, chain id, permit?) - Teecryptor->>TaskManager: ACL check - Teecryptor->>Teecryptor: verify commitment, decrypt in TEE, sign - Teecryptor-->>SDK: plaintext + signature - SDK-->>User: { ctHash, decryptedValue, signature } - User->>TaskManager: FHE.publishDecryptResult(ctHash, result, signature) - TaskManager->>TaskManager: verify signer, store plaintext, emit DecryptionResult - Contract->>TaskManager: FHE.getDecryptResult(handle) - TaskManager-->>Contract: plaintext + participant Chain as Host chain + + App->>SDK: decryptForTx / decryptForView (ctHash) + SDK->>Teecryptor: decrypt or sealoutput request (handle, chain id, permit?) + Teecryptor->>Chain: ACL check (isAllowedWithPermission / isPubliclyAllowed) + Teecryptor->>Teecryptor: verify commitment, decrypt in enclave + alt decryptForTx + Teecryptor-->>SDK: plaintext + signature + SDK-->>App: { ctHash, decryptedValue, signature } + App->>Chain: FHE.publishDecryptResult(ctHash, result, signature) + else decryptForView + Teecryptor-->>SDK: result sealed to the permit's sealing key + SDK->>SDK: unseal locally + SDK-->>App: plaintext + end ``` +## Comparison + +| | `decryptForTx` | `decryptForView` | +|---|---|---| +| **Returns** | Plaintext + Teecryptor signature | Plaintext (sealed in transit, unsealed by the SDK) | +| **Use case** | Submit the decrypted value onchain | Display in a UI, offchain reads | +| **Requires permit** | Only if the handle is not publicly decryptable | Yes | +| **Onchain verification** | `publishDecryptResult` or `verifyDecryptResult` | Not applicable | +| **Gas cost** | None for the decryption itself; gas only for the publish transaction | None | + ## Future plans Decryption is currently performed by Teecryptor inside a hardware-attested TEE. A multi-party Threshold Network is the planned successor; see [Future Plans](/deep-dive/research/future-plans). diff --git a/deep-dive/data-flows/off-chain-decryption-flow.mdx b/deep-dive/data-flows/off-chain-decryption-flow.mdx deleted file mode 100644 index 4d05a1f..0000000 --- a/deep-dive/data-flows/off-chain-decryption-flow.mdx +++ /dev/null @@ -1,194 +0,0 @@ ---- -title: Offchain Decryption Flow -sidebar_position: 4 -description: "How to decrypt CoFHE values with decryptForTx and decryptForView, from ACL grant to plaintext" ---- - -Decryption in CoFHE is SDK-driven. Contracts cannot request it onchain; instead, your application asks [Teecryptor](/deep-dive/cofhe-components/teecryptor) to decrypt a handle it is allowed to read. There are two methods: - -- **`decryptForTx`**: returns the plaintext and a Teecryptor signature. Use it when the decrypted value needs to go onchain, via `FHE.publishDecryptResult` or the `verifyDecryptResult` family. -- **`decryptForView`**: returns the plaintext sealed to your permit. Use it for UI display or offchain reads where no onchain proof is needed. - - -A freshly computed handle may not be decryptable immediately: its ciphertext and commitment land shortly after the transaction. Until then Teecryptor answers with a retryable status and the SDK re-submits automatically. - - -## Key components - -| Component | Description | -| --- | --- | -| **CtHash** | A `bytes32` handle representing an encrypted value, read from the chain. | -| **SDK client** | Client library handling [permits](/client-sdk/guides/permits) and the `decryptForTx` / `decryptForView` operations. | -| **Teecryptor** | Offchain decryption service running in an attested TEE. Verifies access onchain and returns signed or sealed results. | -| **ACL** | Onchain access control list that tracks who may decrypt each handle. | - -## The `decryptForTx` flow - -Use `decryptForTx` when you need to submit the decrypted value onchain with a proof. - - - -Solidity contract: - -```solidity -contract Example { - euint32 public count; - - function setCount(uint32 num) public { - count = FHE.asEuint32(num); - FHE.allowThis(count); - FHE.allowPublic(count); // Allow anyone to request decryption - } -} -``` - -Fetch the `CtHash` from the chain: - -```typescript -const ctHash = await example.count(); -``` - - -All encrypted types (`euint8`, `euint16`, `euint32`, `euint64`, `euint128`, `ebool`, `eaddress`) are wrappers around `bytes32`. The data returned from the contract can be used as a `CtHash` directly. - - - - -Call `decryptForTx` on the SDK client. Since `FHE.allowPublic` was used, no permit is needed: - -```typescript -const result = await client - .decryptForTx(ctHash) - .withoutPermit() - .execute(); -``` - -If the value was granted access via `FHE.allow` (not `allowPublic`), use `.withPermit()` instead: - -```typescript -const result = await client - .decryptForTx(ctHash) - .withPermit() - .execute(); -``` - - - -Behind the scenes: - -1. The SDK sends the request to Teecryptor with the handle, the host chain id, and the permit if one was attached. -2. Teecryptor checks the onchain ACL. With a permit it calls `isAllowedWithPermission` for the permit's issuer; without one, the handle must pass `isPubliclyAllowed`. -3. Teecryptor verifies the stored ciphertext against its onchain commitment and decrypts it inside the enclave. -4. Teecryptor signs the plaintext with its onchain-registered key and returns both the plaintext and the signature. - - - -The SDK returns an object containing the decrypted value and signature. Submit these onchain: - -```typescript -// result contains: { ctHash, decryptedValue, signature } - -await example.revealCount( - result.decryptedValue, - result.signature -); -``` - -The onchain function verifies the signature using `FHE.publishDecryptResult` or `FHE.verifyDecryptResult`: - -```solidity -function revealCount(uint32 _decrypted, bytes memory _signature) external { - FHE.publishDecryptResult(count, _decrypted, _signature); -} -``` - - - -## The `decryptForView` flow - -Use `decryptForView` when you only need to read the value offchain, for example to display it in a UI. No onchain transaction is involved. - - - -The contract must have granted access to the user via `FHE.allow` or `FHE.allowSender`: - -```solidity -contract Example { - mapping(address => euint32) private balances; - - function getBalance() public view returns (euint32) { - return balances[msg.sender]; - } - - function deposit(uint32 amount) public { - balances[msg.sender] = FHE.asEuint32(amount); - FHE.allowThis(balances[msg.sender]); - FHE.allowSender(balances[msg.sender]); // Grant access to the user - } -} -``` - -```typescript -const ctHash = await example.getBalance(); -``` - - - -Call `decryptForView` with a permit and the value's FHE type. The type tells the SDK how to decode the result: - -```typescript -const balance = await client - .decryptForView(ctHash, FheTypes.Uint32) - .withPermit() - .execute(); - -console.log(`Balance: ${balance}`); -``` - -`execute()` returns the decoded plaintext directly. - - - -Behind the scenes: - -1. The SDK sends the request with the user's permit. -2. Teecryptor verifies the permit's EIP-712 signature onchain and checks that the permit's issuer has access to the handle. -3. Teecryptor verifies the ciphertext commitment and decrypts inside the enclave, exactly as in the `decryptForTx` path. -4. Instead of a bare plaintext, Teecryptor returns the result encrypted to the permit's sealing key. The SDK unseals it locally, so the plaintext is never exposed in transit. - - - -## Flow diagram - -```mermaid -%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% -sequenceDiagram - participant App as Your app - participant SDK as Client SDK - participant Teecryptor - participant Chain as Host chain - - App->>SDK: decryptForTx / decryptForView (ctHash) - SDK->>Teecryptor: decrypt or sealoutput request (handle, chain id, permit?) - Teecryptor->>Chain: ACL check (isAllowedWithPermission / isPubliclyAllowed) - Teecryptor->>Teecryptor: verify commitment, decrypt in enclave - alt decryptForTx - Teecryptor-->>SDK: plaintext + signature - SDK-->>App: { ctHash, decryptedValue, signature } - App->>Chain: FHE.publishDecryptResult(ctHash, result, signature) - else decryptForView - Teecryptor-->>SDK: result sealed to the permit's sealing key - SDK->>SDK: unseal locally - SDK-->>App: plaintext - end -``` - -## Comparison - -| | `decryptForTx` | `decryptForView` | -|---|---|---| -| **Returns** | Plaintext + Teecryptor signature | Plaintext (sealed in transit, unsealed by the SDK) | -| **Use case** | Submit the decrypted value onchain | Display in a UI, offchain reads | -| **Requires permit** | Only if the handle is not publicly decryptable | Yes | -| **Onchain verification** | `publishDecryptResult` or `verifyDecryptResult` | Not applicable | -| **Gas cost** | None for the decryption itself; gas only for the publish transaction | None | diff --git a/docs.json b/docs.json index 22a17cf..be9b785 100644 --- a/docs.json +++ b/docs.json @@ -252,8 +252,7 @@ "pages": [ "deep-dive/data-flows/encryption-request-flow", "deep-dive/data-flows/fhe-operation-request-flow", - "deep-dive/data-flows/decryption-request-flow", - "deep-dive/data-flows/off-chain-decryption-flow" + "deep-dive/data-flows/decryption-request-flow" ] }, { @@ -320,6 +319,10 @@ { "source": "/deep-dive/cofhe-components/ct-registry", "destination": "/deep-dive/cofhe-components/commitment-registry" + }, + { + "source": "/deep-dive/data-flows/off-chain-decryption-flow", + "destination": "/deep-dive/data-flows/decryption-request-flow" } ], "integrations": { From 242d1af3f4ed36afe040eae77cde73adc2312802 Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 23 Aug 2026 17:31:24 +0300 Subject: [PATCH 21/58] [DOCS] deep-dive: rename What comes next sections to Future plans for clarity --- deep-dive/cofhe-components/overview.mdx | 2 +- deep-dive/cofhe-components/teecryptor.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index 390c59a..ea2798c 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -74,6 +74,6 @@ Services communicate through message queues rather than direct calls, so each st 2. **[FHE operation flow](/deep-dive/data-flows/fhe-operation-request-flow)**: a contract requests a computation; the coprocessor executes it and commits to the result. 3. **[Decryption](/deep-dive/data-flows/decryption-request-flow)**: the SDK asks Teecryptor to decrypt a handle, either as a signed plaintext for onchain publication or sealed to a permit for offchain reads. -## What comes next +## Future plans Decryption is currently performed by Teecryptor inside a hardware-attested TEE. A multi-party [Threshold Network](/deep-dive/research/future-plans) is the planned successor. diff --git a/deep-dive/cofhe-components/teecryptor.mdx b/deep-dive/cofhe-components/teecryptor.mdx index 2325fed..2c2b6c3 100644 --- a/deep-dive/cofhe-components/teecryptor.mdx +++ b/deep-dive/cofhe-components/teecryptor.mdx @@ -90,6 +90,6 @@ This layout matches what the TaskManager reconstructs in `_computeDecryptResultH Teecryptor's signer address is registered onchain as `decryptResultSigner` in the TaskManager. Only results signed by that address are accepted. -## What comes next +## Future plans Teecryptor concentrates key custody at runtime in a single attested machine. The planned Threshold Network removes that concentration by decrypting through multi-party computation, where no party ever holds the full key. See [Future Plans](/deep-dive/research/future-plans). From d3ec13ccb1c5ab5354ccd0cdb294fe7857461cc9 Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 23 Aug 2026 17:33:00 +0300 Subject: [PATCH 22/58] [DOCS] deep-dive/overview: list the ACL as its own onchain contract --- deep-dive/cofhe-components/overview.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index ea2798c..2915ac6 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -51,7 +51,8 @@ flowchart LR ## The onchain contracts - **FHE.sol**: the Solidity library your contract imports. It exposes arithmetic, comparison, and logical operations on encrypted values, plus access control (`allow`, `allowGlobal`) and decrypt-result verification. -- **[TaskManager](/deep-dive/cofhe-components/task-manager)**: the gateway for all FHE operation requests. It validates requests, emits task events for the offchain services, and manages permissions through the [ACL](/deep-dive/cofhe-components/acl). +- **[TaskManager](/deep-dive/cofhe-components/task-manager)**: the gateway for all FHE operation requests. It validates requests, emits task events for the offchain services, and manages permissions through the ACL. +- **[ACL](/deep-dive/cofhe-components/acl)**: the access control contract. It records who may use or decrypt each handle; all writes to it go through the TaskManager. - **[PlaintextsStorage](/deep-dive/cofhe-components/plaintext-storage)**: stores decrypted results after they are published onchain with a verified Teecryptor signature. - **[CommitmentRegistry](/deep-dive/cofhe-components/commitment-registry)**: lives on a dedicated registry chain and records a hash commitment for every ciphertext the coprocessor produces or verifies. Teecryptor checks it before decrypting anything. From b39d01fbc7c14c49ba464002ba2bd89c70300012 Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 23 Aug 2026 17:42:10 +0300 Subject: [PATCH 23/58] [DOCS] deep-dive: trim governance internals from task-manager and acl ahead of the role-based access control change --- deep-dive/cofhe-components/acl.mdx | 2 +- deep-dive/cofhe-components/task-manager.mdx | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/deep-dive/cofhe-components/acl.mdx b/deep-dive/cofhe-components/acl.mdx index 9bca2b0..28291bc 100644 --- a/deep-dive/cofhe-components/acl.mdx +++ b/deep-dive/cofhe-components/acl.mdx @@ -39,4 +39,4 @@ The last two are what the decryption path runs on. For every `decrypt` or `sealo ## Upgrades -The contract is `UUPSUpgradeable` with owner-gated `_authorizeUpgrade`, ownership is `Ownable2Step`, and storage uses ERC-7201 namespaced slots for upgrade safety. +The contract is UUPS-upgradeable behind a proxy, and storage uses ERC-7201 namespaced slots for upgrade safety. diff --git a/deep-dive/cofhe-components/task-manager.mdx b/deep-dive/cofhe-components/task-manager.mdx index 5530824..d1f96fa 100644 --- a/deep-dive/cofhe-components/task-manager.mdx +++ b/deep-dive/cofhe-components/task-manager.mdx @@ -14,16 +14,14 @@ description: "Onchain entry point for CoFHE integration that initiates FHE opera The TaskManager holds two distinct signer addresses, one per trust boundary: -| Signer | Verifies | Set by | -|--------|----------|--------| -| `verifierSigner` | Encrypted inputs: the ZK Verifier signs each input it verified, and `verifyInput` checks that signature before emitting `InputVerified(ctHash, commitment)`. | Owner | -| `decryptResultSigner` | Decrypt results: [Teecryptor](/deep-dive/cofhe-components/teecryptor) signs each plaintext it returns, and the publish path checks that signature before storing the result. | Owner | - -Either signer set to `address(0)` skips its verification (debug mode only, never in production). +| Signer | Verifies | +|--------|----------| +| `verifierSigner` | Encrypted inputs: the ZK Verifier signs each input it verified, and `verifyInput` checks that signature before emitting `InputVerified(ctHash, commitment)`. | +| `decryptResultSigner` | Decrypt results: [Teecryptor](/deep-dive/cofhe-components/teecryptor) signs each plaintext it returns, and the publish path checks that signature before storing the result. | ## Decrypt result signature verification -The TaskManager supports **permissionless publishing of decrypt results**. Anyone holding a valid signature from the decryption service can publish the result onchain, provided the contract is enabled (the owner holds an `isEnabled` kill switch). Today that signature comes from Teecryptor; a decentralized [Threshold Network](/deep-dive/research/future-plans) is the planned successor. +The TaskManager supports **permissionless publishing of decrypt results**. Anyone holding a valid signature from the decryption service can publish the result onchain. Today that signature comes from Teecryptor; a decentralized [Threshold Network](/deep-dive/research/future-plans) is the planned successor. Verified results are stored in the [PlaintextsStorage](/deep-dive/cofhe-components/plaintext-storage) contract, where any contract can read them back with `getDecryptResult` (reverts with `DecryptionResultNotReady` if pending) or `getDecryptResultSafe` (returns a ready flag). @@ -37,7 +35,7 @@ Verified results are stored in the [PlaintextsStorage](/deep-dive/cofhe-componen | `verifyDecryptResultSafe(ctHash, result, signature)` | Verify a signature without publishing (view). Returns `false` on failure. | | `verifyDecryptResultBatch(ctHashes[], results[], signatures[])` | Batch verify (view). Reverts on the first failure. | | `verifyDecryptResultBatchSafe(ctHashes[], results[], signatures[])` | Batch verify (view). Returns a `bool[]` of per-item outcomes. | -| `setDecryptResultSigner(address)` | Owner-only (two-step ownable). Set the authorized signer address. | +| `setDecryptResultSigner(address)` | Admin-only. Set the authorized signer address. | ### Signature message format @@ -51,7 +49,3 @@ The signed message is a fixed **76-byte** buffer: | `ct_hash` | 32 bytes | uint256, big-endian | The message is hashed with `keccak256` and verified using OpenZeppelin's `ECDSA.tryRecover`. The `enc_type` and `chain_id` are derived onchain, binding each signature to a specific ciphertext type and chain. - -## Upgrades - -The contract is `UUPSUpgradeable` with `_authorizeUpgrade` gated to the owner, and ownership is `Ownable2Step` (transfers require an explicit accept). The constructor calls `_disableInitializers()`, so the implementation contract can never be initialized directly. From 69a41cbe19783abc94c9a7bd8ca99b5d92b324d8 Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 23 Aug 2026 17:47:42 +0300 Subject: [PATCH 24/58] [DOCS] deep-dive: signer list instead of a cramped table, drop pre-role-model governance detail from commitment-registry --- .../cofhe-components/commitment-registry.mdx | 17 ++++------------- deep-dive/cofhe-components/task-manager.mdx | 6 ++---- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/deep-dive/cofhe-components/commitment-registry.mdx b/deep-dive/cofhe-components/commitment-registry.mdx index 1a6996f..b80a835 100644 --- a/deep-dive/cofhe-components/commitment-registry.mdx +++ b/deep-dive/cofhe-components/commitment-registry.mdx @@ -8,7 +8,7 @@ description: "Registry-chain contract that records FHE computation commitments. | **Type** | UUPS-upgradeable Solidity contract deployed on a dedicated **registry chain**. | | **Function** | Records `(version, handle) β†’ commitHash` entries for every FHE operation result that the coprocessor produces. | | **Responsibilities** | β€’ Provide an authoritative source of ciphertext integrity that [Teecryptor](/deep-dive/cofhe-components/teecryptor) checks **before** decrypting.
β€’ Group commitments by an opaque `version` tag so a future tfhe-rs / FHE-parameter upgrade can roll out without invalidating earlier ciphertexts.
β€’ Enforce write-once semantics per `(version, handle)` to prevent commitment replacement.
β€’ Expose paginated enumeration so offchain tooling can audit what has been posted. | -| **Deployment** | One deployment per registry chain, behind an ERC-1967 proxy. Initialized with `(initialOwner, initialPoster)`. Owner is `Ownable2Step`; transfers require an explicit accept. | +| **Deployment** | One deployment per registry chain, behind an ERC-1967 proxy. | ## Why a separate registry chain? @@ -45,16 +45,11 @@ stateDiagram-v2 | `Deprecated` | New commitments rejected. Existing lookups still resolve. Used during a parameter rollover. | to `Revoked` | | `Revoked` | Hard kill. No further transitions; the version is dead. | none (terminal) | -Owner-only `setVersionStatus(version, newStatus)` enforces these transitions and reverts with `InvalidVersionTransition` otherwise. The transition emits `VersionStatusChanged(version, oldStatus, newStatus)`. +The admin-only `setVersionStatus(version, newStatus)` enforces these transitions and reverts with `InvalidVersionTransition` otherwise. The transition emits `VersionStatusChanged(version, oldStatus, newStatus)`. -## Roles and write surface +## Write surface -| Role | How it's set | What it can do | -|------|--------------|----------------| -| **Owner** | `initialize(initialOwner, …)`, then `Ownable2Step` transfer. | `addPoster`, `removePoster`, `setVersionStatus`, `_authorizeUpgrade`. | -| **Poster** | Owner-only `addPoster(address)`. Initial poster supplied to `initialize`. | `postCommitments`, `postCommitmentsSafe`. | - -Non-poster posts revert with `OnlyPosterAllowed(caller)`. In production, the poster role is held by the [`blockchain-poster`](https://github.com/FhenixProtocol/cofhe/blob/master/CHANGELOG.md#060---2026-05-05) service's relayer signer (OpenZeppelin Relayer). +Only accounts holding the **poster** role can write commitments (`postCommitments`, `postCommitmentsSafe`); posts from anyone else revert with `OnlyPosterAllowed(caller)`. Poster management and version transitions are admin-only. In production, the poster role is held by the [`blockchain-poster`](https://github.com/FhenixProtocol/cofhe/blob/master/CHANGELOG.md#060---2026-05-05) service's relayer signer (OpenZeppelin Relayer). ## Writing commitments @@ -111,10 +106,6 @@ The paginated `getHandles` is the recommended way to enumerate a version: `getSi | `VersionStatusChanged(bytes32 indexed version, VersionStatus oldStatus, VersionStatus newStatus)` | `setVersionStatus` | Watch for `Active β†’ Deprecated` to know when to stop posting under a version. | | `PosterAdded(address indexed poster)` / `PosterRemoved(address indexed poster)` | `addPoster` / `removePoster` | Audit role changes. | -## Upgrades - -The contract is `UUPSUpgradeable`. `_authorizeUpgrade` is gated by `onlyOwner`. The constructor calls `_disableInitializers()` so the implementation contract itself can never be initialized; initialization happens through the proxy via `initialize(initialOwner, initialPoster)`. - ## Source - Solidity: [`contracts/internal/registry-chain/contracts/commitment-registry/CommitmentRegistry.sol`](https://github.com/FhenixProtocol/cofhe-contracts/blob/master/contracts/internal/registry-chain/contracts/commitment-registry/CommitmentRegistry.sol). diff --git a/deep-dive/cofhe-components/task-manager.mdx b/deep-dive/cofhe-components/task-manager.mdx index d1f96fa..dce097f 100644 --- a/deep-dive/cofhe-components/task-manager.mdx +++ b/deep-dive/cofhe-components/task-manager.mdx @@ -14,10 +14,8 @@ description: "Onchain entry point for CoFHE integration that initiates FHE opera The TaskManager holds two distinct signer addresses, one per trust boundary: -| Signer | Verifies | -|--------|----------| -| `verifierSigner` | Encrypted inputs: the ZK Verifier signs each input it verified, and `verifyInput` checks that signature before emitting `InputVerified(ctHash, commitment)`. | -| `decryptResultSigner` | Decrypt results: [Teecryptor](/deep-dive/cofhe-components/teecryptor) signs each plaintext it returns, and the publish path checks that signature before storing the result. | +- **`verifierSigner`** covers encrypted inputs: the ZK Verifier signs each input it verified, and `verifyInput` checks that signature before emitting `InputVerified(ctHash, commitment)`. +- **`decryptResultSigner`** covers decrypt results: [Teecryptor](/deep-dive/cofhe-components/teecryptor) signs each plaintext it returns, and the publish path checks that signature before storing the result. ## Decrypt result signature verification From 74e5805a21a748dd8f68aebcd19c282598768998 Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 23 Aug 2026 17:53:27 +0300 Subject: [PATCH 25/58] [DOCS] deep-dive/task-manager: signer table with nowrap column so code names never break --- deep-dive/cofhe-components/task-manager.mdx | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/deep-dive/cofhe-components/task-manager.mdx b/deep-dive/cofhe-components/task-manager.mdx index dce097f..3c61513 100644 --- a/deep-dive/cofhe-components/task-manager.mdx +++ b/deep-dive/cofhe-components/task-manager.mdx @@ -14,8 +14,24 @@ description: "Onchain entry point for CoFHE integration that initiates FHE opera The TaskManager holds two distinct signer addresses, one per trust boundary: -- **`verifierSigner`** covers encrypted inputs: the ZK Verifier signs each input it verified, and `verifyInput` checks that signature before emitting `InputVerified(ctHash, commitment)`. -- **`decryptResultSigner`** covers decrypt results: [Teecryptor](/deep-dive/cofhe-components/teecryptor) signs each plaintext it returns, and the publish path checks that signature before storing the result. + + + + + + + + + + + + + + + + + +
SignerVerifies
verifierSignerEncrypted inputs: the ZK Verifier signs each input it verified, and verifyInput checks that signature before emitting InputVerified(ctHash, commitment).
decryptResultSignerDecrypt results: Teecryptor signs each plaintext it returns, and the publish path checks that signature before storing the result.
## Decrypt result signature verification From eca75507586b791ac96af82e72b14b507da8939b Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 23 Aug 2026 17:59:09 +0300 Subject: [PATCH 26/58] [DOCS] deep-dive/task-manager: nowrap code names in tables, signature moved to prose; STYLE.md rule for code in table columns --- STYLE.md | 2 ++ deep-dive/cofhe-components/task-manager.mdx | 38 +++++++-------------- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/STYLE.md b/STYLE.md index 9b08763..40111a1 100644 --- a/STYLE.md +++ b/STYLE.md @@ -119,6 +119,8 @@ Do not use internal names in public docs: no hostnames, no GCP project names, no A page full of callouts has none. +- Long code identifiers in narrow table columns get chopped mid-word by the table layout. Keep the first column to bare names (no argument lists) and guard each one with `name`. Full signatures belong in prose above the table or in the description column. + ## Code samples - Every sample must compile or run against the currently published versions. If it would not run when pasted, it does not ship. diff --git a/deep-dive/cofhe-components/task-manager.mdx b/deep-dive/cofhe-components/task-manager.mdx index 3c61513..8a78290 100644 --- a/deep-dive/cofhe-components/task-manager.mdx +++ b/deep-dive/cofhe-components/task-manager.mdx @@ -14,24 +14,10 @@ description: "Onchain entry point for CoFHE integration that initiates FHE opera The TaskManager holds two distinct signer addresses, one per trust boundary: - - - - - - - - - - - - - - - - - -
SignerVerifies
verifierSignerEncrypted inputs: the ZK Verifier signs each input it verified, and verifyInput checks that signature before emitting InputVerified(ctHash, commitment).
decryptResultSignerDecrypt results: Teecryptor signs each plaintext it returns, and the publish path checks that signature before storing the result.
+| Signer | Verifies | +|--------|----------| +| verifierSigner | Encrypted inputs: the ZK Verifier signs each input it verified, and `verifyInput` checks that signature before emitting `InputVerified(ctHash, commitment)`. | +| decryptResultSigner | Decrypt results: [Teecryptor](/deep-dive/cofhe-components/teecryptor) signs each plaintext it returns, and the publish path checks that signature before storing the result. | ## Decrypt result signature verification @@ -41,15 +27,17 @@ Verified results are stored in the [PlaintextsStorage](/deep-dive/cofhe-componen ### Functions +All take `(ctHash, result, signature)`; the batch variants take parallel arrays. + | Function | Description | |----------|-------------| -| `publishDecryptResult(ctHash, result, signature)` | Verify the signature and store the decrypt result onchain. Emits `DecryptionResult`. | -| `publishDecryptResultBatch(ctHashes[], results[], signatures[])` | Batch publish multiple results in one transaction for gas efficiency. | -| `verifyDecryptResult(ctHash, result, signature)` | Verify a signature without publishing (view). Reverts on failure. | -| `verifyDecryptResultSafe(ctHash, result, signature)` | Verify a signature without publishing (view). Returns `false` on failure. | -| `verifyDecryptResultBatch(ctHashes[], results[], signatures[])` | Batch verify (view). Reverts on the first failure. | -| `verifyDecryptResultBatchSafe(ctHashes[], results[], signatures[])` | Batch verify (view). Returns a `bool[]` of per-item outcomes. | -| `setDecryptResultSigner(address)` | Admin-only. Set the authorized signer address. | +| publishDecryptResult | Verify the signature and store the decrypt result onchain. Emits `DecryptionResult`. | +| publishDecryptResultBatch | Batch publish multiple results in one transaction for gas efficiency. | +| verifyDecryptResult | Verify a signature without publishing (view). Reverts on failure. | +| verifyDecryptResultSafe | Verify a signature without publishing (view). Returns `false` on failure. | +| verifyDecryptResultBatch | Batch verify (view). Reverts on the first failure. | +| verifyDecryptResultBatchSafe | Batch verify (view). Returns a `bool[]` of per-item outcomes. | +| setDecryptResultSigner | Admin-only. Takes an address; sets the authorized signer. | ### Signature message format From f5708abd02d12e724c774b417dedf46d050c6941 Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 23 Aug 2026 18:02:34 +0300 Subject: [PATCH 27/58] [DOCS] deep-dive/commitment-registry: reframe commitments as safety check and auditability, horizontal state diagram --- deep-dive/cofhe-components/commitment-registry.mdx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/deep-dive/cofhe-components/commitment-registry.mdx b/deep-dive/cofhe-components/commitment-registry.mdx index b80a835..4cf7746 100644 --- a/deep-dive/cofhe-components/commitment-registry.mdx +++ b/deep-dive/cofhe-components/commitment-registry.mdx @@ -10,9 +10,11 @@ description: "Registry-chain contract that records FHE computation commitments. | **Responsibilities** | β€’ Provide an authoritative source of ciphertext integrity that [Teecryptor](/deep-dive/cofhe-components/teecryptor) checks **before** decrypting.
β€’ Group commitments by an opaque `version` tag so a future tfhe-rs / FHE-parameter upgrade can roll out without invalidating earlier ciphertexts.
β€’ Enforce write-once semantics per `(version, handle)` to prevent commitment replacement.
β€’ Expose paginated enumeration so offchain tooling can audit what has been posted. | | **Deployment** | One deployment per registry chain, behind an ERC-1967 proxy. | -## Why a separate registry chain? +## Why commitments? -[Teecryptor](/deep-dive/cofhe-components/teecryptor) needs to confirm that the ciphertext it is about to decrypt is **exactly** the one the FHE Engine produced, not a tampered or stale handle. The natural place to anchor that proof is onchain, but anchoring on every host chain would mean paying gas on N chains for every FHE operation. Instead, the coprocessor posts commitments to a **single registry chain**, and the decryption path watches only that one. +The commitment is a safety check in the decryption flow. Before decrypting anything, [Teecryptor](/deep-dive/cofhe-components/teecryptor) confirms that the ciphertext bytes it fetched hash to the commitment anchored onchain. It only ever decrypts a ciphertext the coprocessor actually produced, never a tampered or substituted one. + +The registry also makes the coprocessor accountable. Every result it has ever produced is committed publicly, permanently, and write-once, so its computation history is tamper-evident and open to independent audit. Commitments for every host chain land on one dedicated **registry chain**, which gives the decryption path a single place to verify against. ## Storage shape @@ -32,6 +34,7 @@ mapping(address => bool) poster ```mermaid %%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% stateDiagram-v2 + direction LR Unset --> Active Active --> Deprecated Active --> Revoked From 5a386a723e004134aa21d8c171f094ed179dc143 Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 23 Aug 2026 19:51:12 +0300 Subject: [PATCH 28/58] [DOCS] deep-dive: use the real component name CT Server --- deep-dive/cofhe-components/overview.mdx | 4 ++-- deep-dive/cofhe-components/teecryptor.mdx | 4 ++-- deep-dive/cofhe-components/zk-verifier.mdx | 2 +- deep-dive/data-flows/encryption-request-flow.mdx | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index 2915ac6..4d199c9 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -23,7 +23,7 @@ flowchart LR SL["Slim Listener"] FheOS["FheOS Server"] Engine["FHE Engine"] - CTS["Ciphertext Server"] + CTS["CT Server"] BP["Blockchain Poster"] TEE["Teecryptor (TEE)"] end @@ -63,7 +63,7 @@ flowchart LR - **[Slim Listener](/deep-dive/cofhe-components/slim-listener)**: watches TaskManager events on each host chain and forwards them into the coprocessor's queues. - **[FheOS Server](/deep-dive/cofhe-components/fheos-server)**: ingests task events, verifies inputs, creates result placeholders, and routes work to the FHE Engine. It does not execute FHE operations itself. - **[FHE Engine](/deep-dive/cofhe-components/fhe-engine)**: executes every FHE operation on encrypted data, persists the resulting ciphertexts, and emits a commitment for each result. -- **Ciphertext Server**: stores and serves ciphertext bytes to the other services. +- **CT Server**: the ciphertext store. It holds the ciphertext bytes and serves them to the other services. - **Blockchain Poster**: batches result commitments and posts them to the CommitmentRegistry. - **[Teecryptor](/deep-dive/cofhe-components/teecryptor)**: the decryption service. It runs inside a hardware-attested TEE, authorizes every request against the onchain ACL, verifies the ciphertext commitment, and returns signed or sealed results. diff --git a/deep-dive/cofhe-components/teecryptor.mdx b/deep-dive/cofhe-components/teecryptor.mdx index 2c2b6c3..7533d43 100644 --- a/deep-dive/cofhe-components/teecryptor.mdx +++ b/deep-dive/cofhe-components/teecryptor.mdx @@ -26,7 +26,7 @@ Concurrently with authorization, Teecryptor confirms that the [FHE Engine](/deep -The ciphertext is fetched from the ciphertext store exactly as the FHE Engine stored it, and its bytes must hash to the onchain commitment. A missing commitment or mismatched bytes rejects the request. This validates the ciphertext against the onchain commitment before anything is decrypted: Teecryptor only ever decrypts bytes the coprocessor committed to publicly. +The ciphertext is fetched from the CT Server exactly as the FHE Engine stored it, and its bytes must hash to the onchain commitment. A missing commitment or mismatched bytes rejects the request. This validates the ciphertext against the onchain commitment before anything is decrypted: Teecryptor only ever decrypts bytes the coprocessor committed to publicly. @@ -50,7 +50,7 @@ sequenceDiagram participant Teecryptor participant TaskManager participant Registry as CommitmentRegistry - participant Store as Ciphertext store + participant Store as CT Server SDK->>Teecryptor: decrypt / sealoutput (handle, chain id, permit?) par Authorization diff --git a/deep-dive/cofhe-components/zk-verifier.mdx b/deep-dive/cofhe-components/zk-verifier.mdx index f75f435..7949d1b 100644 --- a/deep-dive/cofhe-components/zk-verifier.mdx +++ b/deep-dive/cofhe-components/zk-verifier.mdx @@ -45,7 +45,7 @@ Most of this process is abstracted away. Steps 1 to 6 all happen behind the SDK ## Trust model -The ZK Verifier runs inside a hardware-attested TEE (Intel TDX). Its signing key is released only to the exact attested code image, so neither the operator nor anyone else can sign approvals outside the reviewed program. After a successful verification, the service stores the ciphertext bytes in the coprocessor's ciphertext store and archives the inputs and proofs for auditability. +The ZK Verifier runs inside a hardware-attested TEE (Intel TDX). Its signing key is released only to the exact attested code image, so neither the operator nor anyone else can sign approvals outside the reviewed program. After a successful verification, the service stores the ciphertext bytes in the CT Server and archives the inputs and proofs for auditability. The signed message is verified onchain by the TaskManager using `ecrecover`; the verifier's signer address is registered there as `verifierSigner`. diff --git a/deep-dive/data-flows/encryption-request-flow.mdx b/deep-dive/data-flows/encryption-request-flow.mdx index 313b550..7b8e455 100644 --- a/deep-dive/data-flows/encryption-request-flow.mdx +++ b/deep-dive/data-flows/encryption-request-flow.mdx @@ -12,7 +12,7 @@ This page follows an encrypted input from the plaintext in your application to a | **dApp** | The application that interacts with the user and the contracts | | **Client SDK** (`@cofhe/sdk`) | TypeScript library that encrypts inputs locally and submits them for verification | | **ZK Verifier** | Attested offchain service that verifies the proof attached to every encrypted input | -| **Ciphertext Server** | Stores the verified ciphertext bytes for the coprocessor | +| **CT Server** | Stores the verified ciphertext bytes for the coprocessor | | **[TaskManager](/deep-dive/cofhe-components/task-manager)** | Verifies the ZK Verifier's signature when the input is used onchain | ## Flow diagram @@ -23,7 +23,7 @@ sequenceDiagram participant App as Your app participant SDK as Client SDK participant ZK as ZK Verifier - participant CTS as Ciphertext Server + participant CTS as CT Server participant TM as TaskManager App->>SDK: encryptInputs([...]).execute() From 846551388dff8be04410217d7f13d4f0787748da Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 23 Aug 2026 19:59:05 +0300 Subject: [PATCH 29/58] [DOCS] deep-dive: sweep fixes (links, cross-page consistency, tone, table guards) and readable diagram sizing --- deep-dive/cofhe-components/acl.mdx | 4 ++-- .../cofhe-components/commitment-registry.mdx | 20 +++++++++---------- deep-dive/cofhe-components/overview.mdx | 8 ++++---- .../cofhe-components/plaintext-storage.mdx | 4 ++-- deep-dive/cofhe-components/teecryptor.mdx | 6 +++--- deep-dive/cofhe-components/zk-verifier.mdx | 12 +++++------ .../data-flows/decryption-request-flow.mdx | 4 ++-- .../data-flows/encryption-request-flow.mdx | 4 +++- .../data-flows/fhe-operation-request-flow.mdx | 6 +++--- scripts/mermaid-theme.json | 7 +++++-- 10 files changed, 40 insertions(+), 35 deletions(-) diff --git a/deep-dive/cofhe-components/acl.mdx b/deep-dive/cofhe-components/acl.mdx index 28291bc..3dae324 100644 --- a/deep-dive/cofhe-components/acl.mdx +++ b/deep-dive/cofhe-components/acl.mdx @@ -33,9 +33,9 @@ All state-mutating entry points require `msg.sender` to be the TaskManager; dire | `persistAllowed(handle, account)` | Is there a persistent grant? | | `globalAllowed(handle)` | Is the handle globally allowed? | | `isAllowedForDecryption(handle)` | Is the handle on the decryption allowlist? | -| `isAllowedWithPermission(permission, handle)` | Does this EIP-712 [permit](/client-sdk/guides/permits) authorize its issuer for the handle? | +| isAllowedWithPermission | Does this EIP-712 [permit](/client-sdk/guides/permits) authorize its issuer for the given handle? | -The last two are what the decryption path runs on. For every `decrypt` or `sealoutput` request, Teecryptor queries the ACL through the TaskManager: `isAllowedWithPermission` when a permit is attached, or the public-decryptability check when none is. A future [Threshold Network](/deep-dive/research/future-plans) will consume the same interface. +The last two are what the decryption path runs on. For every `decrypt` or `sealoutput` request, Teecryptor queries the ACL through the TaskManager: `isAllowedWithPermission` when a permit is attached, or `isPubliclyAllowed` (the TaskManager's wrapper over `globalAllowed`) when none is. A future [Threshold Network](/deep-dive/research/future-plans) will consume the same interface. ## Upgrades diff --git a/deep-dive/cofhe-components/commitment-registry.mdx b/deep-dive/cofhe-components/commitment-registry.mdx index 4cf7746..6e38156 100644 --- a/deep-dive/cofhe-components/commitment-registry.mdx +++ b/deep-dive/cofhe-components/commitment-registry.mdx @@ -6,7 +6,7 @@ description: "Registry-chain contract that records FHE computation commitments. | Aspect | Description | |--------|-------------| | **Type** | UUPS-upgradeable Solidity contract deployed on a dedicated **registry chain**. | -| **Function** | Records `(version, handle) β†’ commitHash` entries for every FHE operation result that the coprocessor produces. | +| **Function** | Records `(version, handle) β†’ commitHash` entries for every ciphertext the coprocessor produces or verifies, computed results and encrypted inputs alike. | | **Responsibilities** | β€’ Provide an authoritative source of ciphertext integrity that [Teecryptor](/deep-dive/cofhe-components/teecryptor) checks **before** decrypting.
β€’ Group commitments by an opaque `version` tag so a future tfhe-rs / FHE-parameter upgrade can roll out without invalidating earlier ciphertexts.
β€’ Enforce write-once semantics per `(version, handle)` to prevent commitment replacement.
β€’ Expose paginated enumeration so offchain tooling can audit what has been posted. | | **Deployment** | One deployment per registry chain, behind an ERC-1967 proxy. | @@ -29,10 +29,10 @@ mapping(address => bool) poster ## Version lifecycle -`version` is an opaque `bytes32` tag chosen by the coprocessor when FHE parameters change, currently the ASCII tag `"2"` (see [the FHE Engine `COMMITMENT_VERSION` notes](https://github.com/FhenixProtocol/cofhe/blob/master/CHANGELOG.md#060---2026-05-05)). Every version moves through a small state machine: +`version` is an opaque `bytes32` tag chosen by the coprocessor when FHE parameters change, currently the ASCII tag `"2"` (see [the `COMMITMENT_VERSION` changelog notes](https://github.com/FhenixProtocol/cofhe/blob/master/CHANGELOG.md#060---2026-05-05)). Every version moves through a small state machine: ```mermaid -%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220, "actorFontSize": 16, "messageFontSize": 16, "noteFontSize": 15}}}%% stateDiagram-v2 direction LR Unset --> Active @@ -52,7 +52,7 @@ The admin-only `setVersionStatus(version, newStatus)` enforces these transitions ## Write surface -Only accounts holding the **poster** role can write commitments (`postCommitments`, `postCommitmentsSafe`); posts from anyone else revert with `OnlyPosterAllowed(caller)`. Poster management and version transitions are admin-only. In production, the poster role is held by the [`blockchain-poster`](https://github.com/FhenixProtocol/cofhe/blob/master/CHANGELOG.md#060---2026-05-05) service's relayer signer (OpenZeppelin Relayer). +Only accounts holding the **poster** role can write commitments (`postCommitments`, `postCommitmentsSafe`); posts from anyone else revert with `OnlyPosterAllowed(caller)`. Poster management and version transitions are admin-only. In production, the poster role is held by the [`blockchain-poster`](https://github.com/FhenixProtocol/cofhe/tree/master/src/services/blockchain-poster) service's relayer signer (OpenZeppelin Relayer). ## Writing commitments @@ -94,8 +94,8 @@ Both enforce **write-once per (version, handle)**: a commitment can never be ove | `getCommitment(version, handle)` | `bytes32` | `bytes32(0)` means "not posted". | | `getVersionStatus(version)` | `VersionStatus` | `Unset` if never registered. | | `getSize(version)` | `uint256` | Number of handles ever committed under `version`. | -| `getHandleByIndex(version, index)` | `bytes32` | Direct array lookup. Reverts on out-of-range. | -| `getHandles(version, offset, limit)` | `bytes32[]` | Paginated. Returns an empty array if `offset >= total`; clamps `offset + limit` at `total`. | +| getHandleByIndex(version, index) | `bytes32` | Direct array lookup. Reverts on out-of-range. | +| getHandles(version, offset, limit) | `bytes32[]` | Paginated. Returns an empty array if `offset >= total`; clamps `offset + limit` at `total`. | | `isPoster(address)` | `bool` | Useful for offchain ops dashboards. | The paginated `getHandles` is the recommended way to enumerate a version: `getSize` first to compute pages, then `getHandles(version, offset, pageSize)` in a loop. @@ -104,10 +104,10 @@ The paginated `getHandles` is the recommended way to enumerate a version: `getSi | Event | Emitted by | Use | |-------|-----------|-----| -| `CommitmentsPosted(bytes32 indexed version, uint256 batchSize)` | `postCommitments` | Confirm a strict batch landed. | -| `CommitmentsPostedSafe(bytes32 indexed version, uint256 newlyPosted, uint256 skipped)` | `postCommitmentsSafe` | Reconcile "how many were new" in an idempotent flow. | -| `VersionStatusChanged(bytes32 indexed version, VersionStatus oldStatus, VersionStatus newStatus)` | `setVersionStatus` | Watch for `Active β†’ Deprecated` to know when to stop posting under a version. | -| `PosterAdded(address indexed poster)` / `PosterRemoved(address indexed poster)` | `addPoster` / `removePoster` | Audit role changes. | +| CommitmentsPosted | `postCommitments` | Confirm a strict batch landed. Carries the version and batch size. | +| CommitmentsPostedSafe | `postCommitmentsSafe` | Reconcile "how many were new" in an idempotent flow. Carries newlyPosted and skipped counts. | +| VersionStatusChanged | `setVersionStatus` | Watch for the `Active` to `Deprecated` transition to know when to stop posting under a version. | +| PosterAdded / PosterRemoved | `addPoster` / `removePoster` | Audit role changes. | ## Source diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index 4d199c9..f61701c 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -3,11 +3,11 @@ title: "CoFHE Architecture Overview" description: "How CoFHE's onchain contracts and offchain services fit together to run FHE computations for any EVM chain" --- -CoFHE (Coprocessor for Fully Homomorphic Encryption) lets smart contracts compute on encrypted data. Contracts request operations through onchain calls; a set of offchain services executes them and commits to the results. Data stays encrypted through the entire lifecycle, and every result can be verified against an onchain commitment. +CoFHE (Coprocessor for Fully Homomorphic Encryption) lets smart contracts compute on encrypted data. Contracts request operations through onchain calls; a set of offchain services executes them and commits to the results. Data stays encrypted until an authorized decryption, and every result can be verified against an onchain commitment. ```mermaid -%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% -flowchart LR +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220, "actorFontSize": 16, "messageFontSize": 16, "noteFontSize": 15}}}%% +flowchart TB subgraph App["Application"] SDK["Client SDK"] end @@ -20,10 +20,10 @@ flowchart LR subgraph CoFHE["CoFHE services (offchain)"] ZK["ZK Verifier"] + CTS["CT Server"] SL["Slim Listener"] FheOS["FheOS Server"] Engine["FHE Engine"] - CTS["CT Server"] BP["Blockchain Poster"] TEE["Teecryptor (TEE)"] end diff --git a/deep-dive/cofhe-components/plaintext-storage.mdx b/deep-dive/cofhe-components/plaintext-storage.mdx index 2c53bf0..05e1688 100644 --- a/deep-dive/cofhe-components/plaintext-storage.mdx +++ b/deep-dive/cofhe-components/plaintext-storage.mdx @@ -1,5 +1,5 @@ --- -title: Plaintexts Storage +title: PlaintextsStorage description: "Host-chain contract that stores published decryption results so contracts can read them synchronously" --- @@ -11,4 +11,4 @@ description: "Host-chain contract that stores published decryption results so co Decryption happens offchain, but contracts need the result onchain. When a signed decrypt result is published through `FHE.publishDecryptResult`, the [TaskManager](/deep-dive/cofhe-components/task-manager) verifies the signature and writes the plaintext here. Only the TaskManager can write to this contract. -Contracts read results back with `FHE.getDecryptResult(handle)`, which reverts if the result is not yet published, or `FHE.getDecryptResultSafe(handle)`, which returns a ready flag instead. See the [Decryption Request Flow](/deep-dive/data-flows/decryption-request-flow) for the full path. +Contracts read results back with `FHE.getDecryptResult(handle)`, which reverts if the result is not yet published, or `FHE.getDecryptResultSafe(handle)`, which returns a ready flag instead. See the [Decryption Flow](/deep-dive/data-flows/decryption-request-flow) for the full path. diff --git a/deep-dive/cofhe-components/teecryptor.mdx b/deep-dive/cofhe-components/teecryptor.mdx index 7533d43..4827d50 100644 --- a/deep-dive/cofhe-components/teecryptor.mdx +++ b/deep-dive/cofhe-components/teecryptor.mdx @@ -22,11 +22,11 @@ Teecryptor checks the handle against the onchain ACL through the [TaskManager](/
-Concurrently with authorization, Teecryptor confirms that the [FHE Engine](/deep-dive/cofhe-components/fheos-server) posted a commitment for this handle in the [CommitmentRegistry](/deep-dive/cofhe-components/commitment-registry). Commitments are write-once, so a verified result is cached permanently. +Concurrently with authorization, Teecryptor confirms that the [FHE Engine](/deep-dive/cofhe-components/fhe-engine) posted a commitment for this handle in the [CommitmentRegistry](/deep-dive/cofhe-components/commitment-registry). Commitments are write-once, so a verified result is cached permanently. -The ciphertext is fetched from the CT Server exactly as the FHE Engine stored it, and its bytes must hash to the onchain commitment. A missing commitment or mismatched bytes rejects the request. This validates the ciphertext against the onchain commitment before anything is decrypted: Teecryptor only ever decrypts bytes the coprocessor committed to publicly. +The ciphertext is fetched from the CT Server exactly as the FHE Engine stored it, and its bytes must hash to the onchain commitment. A missing commitment or mismatched bytes rejects the request. Teecryptor only ever decrypts bytes the coprocessor committed to publicly. @@ -44,7 +44,7 @@ A handle whose ciphertext or commitment has not landed yet is not an error. Teec ```mermaid -%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220, "actorFontSize": 16, "messageFontSize": 16, "noteFontSize": 15}}}%% sequenceDiagram participant SDK as Client SDK participant Teecryptor diff --git a/deep-dive/cofhe-components/zk-verifier.mdx b/deep-dive/cofhe-components/zk-verifier.mdx index 7949d1b..ce41272 100644 --- a/deep-dive/cofhe-components/zk-verifier.mdx +++ b/deep-dive/cofhe-components/zk-verifier.mdx @@ -3,17 +3,17 @@ title: ZK Verifier description: "Offchain service that verifies user inputs using Zero-Knowledge Proofs of Knowledge (ZKPoK) to ensure encrypted data is safe to use in smart contracts" --- -**ZK Verifier** is an essential component for encrypting and providing data as inputs to confidential smart contracts. +**ZK Verifier** checks every encrypted input before it can enter a confidential smart contract. | Aspect | Description | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Type** | Offchain service running inside a hardware-attested TEE, used by clients. | +| **Type** | Offchain service running inside a hardware-attested TEE. | | **Function** | Verifies the user's input, ensuring that it is safe to use. | -| **Responsibilities** | β€’ Receives users' ZKPoKs for their inputs.
β€’ Verifies said ZK proofs.
β€’ Signs an approval the user passes with the inputs to the contract.
β€’ Stores the verified ciphertext bytes. | +| **Responsibilities** | β€’ Receives users' ZKPoKs for their inputs.
β€’ Verifies those proofs.
β€’ Signs an approval the user passes with the inputs to the contract.
β€’ Stores the verified ciphertext bytes. | ## Why ZKPoK? -**Zero-Knowledge Proof of Knowledge (ZKPoK)** provides a crucial security mechanism in CoFHE. It allows users to prove they know the plaintext of an encrypted input they're sending to a smart contract, without revealing the plaintext itself. +A **Zero-Knowledge Proof of Knowledge (ZKPoK)** lets a user prove they know the plaintext behind an encrypted input, without revealing that plaintext. ZKPoKs protect against potential malicious vectors, including: @@ -21,7 +21,7 @@ ZKPoKs protect against potential malicious vectors, including: 2. **Chosen ciphertext attacks (CCAs)**: Attackers submit modified ciphertexts and observe the results, potentially exploiting homomorphic operations to infer sensitive information or even recover the secret key. -Requiring a ZKPoK for each encrypted input is what makes it safe to run an encryption system in a public runtime like a blockchain. It ensures that only users with knowledge of the original plaintext can produce valid proofs. This eliminates multiple security risks, protecting sensitive user data and maintaining the system's integrity. +Requiring a ZKPoK for each encrypted input is what makes it safe to run an encryption system in a public runtime like a blockchain. Only someone who knows the original plaintext can produce a valid proof. ## Sending encrypted inputs @@ -56,7 +56,7 @@ For developers integrating without the SDK, the signed pre-image is: ```text message_to_sign = keccak256( ct_hash (32 bytes) || ct_type (1 byte) || security_zone (1 byte) - || account_addr (bytes) || chain_id (32 bytes, big-endian) + || account_addr (20 bytes, the sender's address) || chain_id (32 bytes, big-endian) ) ``` diff --git a/deep-dive/data-flows/decryption-request-flow.mdx b/deep-dive/data-flows/decryption-request-flow.mdx index 9b7945d..3c40906 100644 --- a/deep-dive/data-flows/decryption-request-flow.mdx +++ b/deep-dive/data-flows/decryption-request-flow.mdx @@ -89,7 +89,7 @@ For `decryptForView`, Teecryptor never returns a bare plaintext. It encrypts the ## Flow diagram ```mermaid -%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220, "actorFontSize": 16, "messageFontSize": 16, "noteFontSize": 15}}}%% sequenceDiagram participant App as Your app participant SDK as Client SDK @@ -118,7 +118,7 @@ sequenceDiagram | **Returns** | Plaintext + Teecryptor signature | Plaintext (sealed in transit, unsealed by the SDK) | | **Use case** | Submit the decrypted value onchain | Display in a UI, offchain reads | | **Requires permit** | Only if the handle is not publicly decryptable | Yes | -| **Onchain verification** | `publishDecryptResult` or `verifyDecryptResult` | Not applicable | +| **Onchain verification** | publishDecryptResult or verifyDecryptResult | Not applicable | | **Gas cost** | None for the decryption itself; gas only for the publish transaction | None | ## Future plans diff --git a/deep-dive/data-flows/encryption-request-flow.mdx b/deep-dive/data-flows/encryption-request-flow.mdx index 7b8e455..f61b4b1 100644 --- a/deep-dive/data-flows/encryption-request-flow.mdx +++ b/deep-dive/data-flows/encryption-request-flow.mdx @@ -18,13 +18,14 @@ This page follows an encrypted input from the plaintext in your application to a ## Flow diagram ```mermaid -%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220, "actorFontSize": 16, "messageFontSize": 16, "noteFontSize": 15}}}%% sequenceDiagram participant App as Your app participant SDK as Client SDK participant ZK as ZK Verifier participant CTS as CT Server participant TM as TaskManager + participant CR as CommitmentRegistry App->>SDK: encryptInputs([...]).execute() SDK->>SDK: encrypt with TFHE, generate zkPoK @@ -35,6 +36,7 @@ sequenceDiagram SDK-->>App: encrypted inputs (InEuint structures) App->>TM: contract call with the encrypted input TM->>TM: verify signature, emit InputVerified + TM--)CR: input commitment (relayed by the coprocessor) ``` ## Step-by-step flow diff --git a/deep-dive/data-flows/fhe-operation-request-flow.mdx b/deep-dive/data-flows/fhe-operation-request-flow.mdx index 1a658a6..fdb7368 100644 --- a/deep-dive/data-flows/fhe-operation-request-flow.mdx +++ b/deep-dive/data-flows/fhe-operation-request-flow.mdx @@ -22,7 +22,7 @@ This page follows a single FHE operation from the contract call that requests it ## Flow diagram ```mermaid -%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "13px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220}}}%% +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220, "actorFontSize": 16, "messageFontSize": 16, "noteFontSize": 15}}}%% sequenceDiagram participant Contract as Your contract (FHE.sol) participant TM as TaskManager @@ -88,7 +88,7 @@ The TaskManager is the gateway for all FHE operation requests. It:
-One Slim Listener instance runs per host chain. It watches for `TaskCreated` events and publishes them to the coprocessor's `blockchain-events` queue. +One Slim Listener instance runs per host chain per flow. This flow's listener watches for `TaskCreated` events and publishes them to the coprocessor's `blockchain-events` queue. @@ -100,7 +100,7 @@ The FHE Engine consumes `engine-requests` and: 1. Executes the requested operation on the encrypted data. 2. Stores the result ciphertext in the coprocessor's store, keyed by the handle. -3. Resolves any queued operations that were waiting on this handle. +3. Releases any dependent operations that were deferred while waiting for this result. 4. Publishes a commitment for the result (the hash of the stored ciphertext bytes) to the `commitment-requests` queue. diff --git a/scripts/mermaid-theme.json b/scripts/mermaid-theme.json index ab4246e..95fe342 100644 --- a/scripts/mermaid-theme.json +++ b/scripts/mermaid-theme.json @@ -2,7 +2,7 @@ "theme": "base", "themeVariables": { "fontFamily": "Menlo, Monaco, Consolas, monospace", - "fontSize": "13px", + "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", @@ -33,6 +33,9 @@ "actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", - "width": 220 + "width": 220, + "actorFontSize": 16, + "messageFontSize": 16, + "noteFontSize": 15 } } \ No newline at end of file From 69cca473b77049e72191998f888091b9dfe1dd99 Mon Sep 17 00:00:00 2001 From: haim Date: Mon, 24 Aug 2026 11:18:27 +0300 Subject: [PATCH 30/58] [DOCS] deep-dive/encryption-request-flow: batch input verification with contract-bound proof (ACP upgrade) --- .DS_Store | Bin 8196 -> 8196 bytes .../data-flows/encryption-request-flow.mdx | 35 +++++++++--------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/.DS_Store b/.DS_Store index bab4cdea050f488cd390ea02ce29efcbddf3cf17..474be5d7efe69d5573b19471c695e72f7e427dc5 100644 GIT binary patch delta 59 zcmZp1XmOa}FQ~!5z`)4BAi$85ZWx@LpIfl8a2or>2Eonj94s7+8k^?`WCOVqHnU57 OW7*s*TE#T6p%(z>SDK: encryptInputs([...]).execute() - SDK->>SDK: encrypt with TFHE, generate zkPoK - SDK->>ZK: ciphertext + proof - ZK->>ZK: verify the proof in the attested TEE + App->>SDK: encryptInputs([...]).setConsumingContract(addr).execute() + SDK->>SDK: encrypt with TFHE, generate zkPoKs + SDK->>ZK: ciphertext batch + proofs + ZK->>ZK: verify the proofs in the attested TEE ZK->>CTS: store ciphertext bytes - ZK-->>SDK: handle + signature per input - SDK-->>App: encrypted inputs (InEuint structures) - App->>TM: contract call with the encrypted input - TM->>TM: verify signature, emit InputVerified - TM--)CR: input commitment (relayed by the coprocessor) + ZK-->>SDK: handles + one batch signature + SDK-->>App: [handles..., proof] + App->>TM: contract call with handles + proof + TM->>TM: batchVerifyInputs, emit InputVerified per input + TM--)CR: input commitments (relayed by the coprocessor) ``` ## Step-by-step flow @@ -56,23 +56,24 @@ const { createCofheConfig, createCofheClient } = require("@cofhe/sdk/node"); -The application encrypts its values with a single builder call: +The application encrypts its values with a single builder call, naming the contract that will consume them: ```typescript -const [encryptedInput] = await cofheClient +const [encryptedInput, proof] = await cofheClient .encryptInputs([Encryptable.uint32(42n)]) + .setConsumingContract(contractAddress) .execute(); ``` -Internally, `encryptInputs` encrypts each value with the TFHE library and generates a zkPoK (zero-knowledge proof of knowledge) that the encryption is correct. It then submits the ciphertext and proof to the ZK Verifier. +Internally, `encryptInputs` encrypts each value with the TFHE library and generates a zkPoK (zero-knowledge proof of knowledge) that the encryption is correct. It then submits the whole batch to the ZK Verifier. The verifier's signature is bound to the consuming contract, so the batch cannot be replayed into a different one. -The ZK Verifier checks the proof inside its attested enclave. A valid proof shows the ciphertext is a correct, untampered encryption of a known plaintext. On success, the verifier stores the ciphertext bytes and returns a handle and a signature per input. The SDK packages these into the `InEuint` structures your contract accepts. +The ZK Verifier checks each proof inside its attested enclave. A valid proof shows the ciphertext is a correct, untampered encryption of a known plaintext. On success, the verifier stores the ciphertext bytes and returns the handles with one signature covering the batch. The SDK hands your application the tuple `[handles..., proof]`; each handle is an `external` encrypted value such as `externalEuint32`. -The application passes the `InEuint` structure to the contract as an encrypted input. When the contract consumes it, the TaskManager verifies the ZK Verifier's signature and emits an `InputVerified` event. The coprocessor picks that event up and posts a commitment for the input to the CommitmentRegistry, so the ciphertext is anchored onchain like every computed result. +The application passes the handles and the proof to the contract as encrypted inputs. When the contract consumes them, the TaskManager's `batchVerifyInputs` checks the ZK Verifier's signature over the batch and emits an `InputVerified` event per input. The coprocessor picks those events up and posts a commitment for each input to the CommitmentRegistry, so the ciphertexts are anchored onchain like every computed result. From 78b9108449e39969799714406fb3af1cd44a8e53 Mon Sep 17 00:00:00 2001 From: haim Date: Mon, 24 Aug 2026 11:18:43 +0300 Subject: [PATCH 31/58] [DOCS] deep-dive/fhe-operation-request-flow: externalEuint input with batch proof (ACP upgrade) --- deep-dive/data-flows/fhe-operation-request-flow.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deep-dive/data-flows/fhe-operation-request-flow.mdx b/deep-dive/data-flows/fhe-operation-request-flow.mdx index fdb7368..e93ed51 100644 --- a/deep-dive/data-flows/fhe-operation-request-flow.mdx +++ b/deep-dive/data-flows/fhe-operation-request-flow.mdx @@ -47,7 +47,7 @@ sequenceDiagram -The application encrypts its input client-side with the [Client SDK](/client-sdk/introduction/overview) (`@cofhe/sdk`) and proves it valid, producing an `InEuint` structure the contract can accept. The [Encryption Request Flow](/deep-dive/data-flows/encryption-request-flow) covers this step. +The application encrypts its input client-side and proves it valid, producing an encrypted-input handle plus a batch proof the contract can accept. The [Encryption Request Flow](/deep-dive/data-flows/encryption-request-flow) covers this step. This step happens on the client side, before any blockchain interaction. @@ -64,9 +64,9 @@ import "@fhenixprotocol/cofhe-contracts/FHE.sol"; Call the appropriate FHE function from the imported library: ```solidity -// Using trivial encrypt or the structure returned by the previous step. -function addExample(InEuint32 memory encryptedInput) public { - euint32 lhs = FHE.asEuint32(encryptedInput); +// Using trivial encrypt or the handle and proof from the previous step. +function addExample(externalEuint32 input, bytes calldata proof) public { + euint32 lhs = FHE.asEuint32(input, proof); euint32 rhs = FHE.asEuint32(10); // Request an operation (addition in this example) From 7c1d80db62bfc4c3c7936256a33962446d2a1efb Mon Sep 17 00:00:00 2001 From: haim Date: Mon, 24 Aug 2026 11:19:50 +0300 Subject: [PATCH 32/58] [DOCS] deep-dive/task-manager: batchVerifyInputs with contract-bound batch signature (ACP upgrade) --- deep-dive/cofhe-components/task-manager.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deep-dive/cofhe-components/task-manager.mdx b/deep-dive/cofhe-components/task-manager.mdx index 8a78290..4cc37d9 100644 --- a/deep-dive/cofhe-components/task-manager.mdx +++ b/deep-dive/cofhe-components/task-manager.mdx @@ -16,7 +16,7 @@ The TaskManager holds two distinct signer addresses, one per trust boundary: | Signer | Verifies | |--------|----------| -| verifierSigner | Encrypted inputs: the ZK Verifier signs each input it verified, and `verifyInput` checks that signature before emitting `InputVerified(ctHash, commitment)`. | +| verifierSigner | Encrypted inputs: the ZK Verifier signs each verified batch, and `batchVerifyInputs` checks that signature before emitting `InputVerified(ctHash, commitment)` per input. The signature binds the consuming contract, so a batch cannot be replayed elsewhere. | | decryptResultSigner | Decrypt results: [Teecryptor](/deep-dive/cofhe-components/teecryptor) signs each plaintext it returns, and the publish path checks that signature before storing the result. | ## Decrypt result signature verification From de395ac21bb612d8454d9701b9d4e1b20ca84714 Mon Sep 17 00:00:00 2001 From: haim Date: Mon, 24 Aug 2026 11:19:50 +0300 Subject: [PATCH 33/58] [DOCS] deep-dive/acl: permits defined as ACP with scopes, sharing and revocation (ACP upgrade) --- deep-dive/cofhe-components/acl.mdx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/deep-dive/cofhe-components/acl.mdx b/deep-dive/cofhe-components/acl.mdx index 3dae324..6281607 100644 --- a/deep-dive/cofhe-components/acl.mdx +++ b/deep-dive/cofhe-components/acl.mdx @@ -24,6 +24,12 @@ Every encrypted value in CoFHE is guarded by this contract. A handle is useless All state-mutating entry points require `msg.sender` to be the TaskManager; direct calls revert with `DirectAllowForbidden`. Contracts grant access through the `FHE.sol` helpers (`allow`, `allowThis`, `allowSender`, `allowGlobal`, `allowTransient`), which route through the TaskManager. +## Permits + +Offchain reads are authorized by a [permit](/client-sdk/guides/permits), which onchain is an `ACP` (Access Control Permission): an EIP-712 body signed by its issuer. Beyond the issuer, expiration, and the sealing key used for sealed outputs, an ACP carries a **scope**: global, limited to specific contracts, or limited to specific handles. A scope only narrows what the issuer could already access; it never grants more. + +An ACP can be shared with a recipient, revoked through a revoker contract, and handed over onchain through the ACP share registry. + ## Read surface | Function | Answers | @@ -33,7 +39,7 @@ All state-mutating entry points require `msg.sender` to be the TaskManager; dire | `persistAllowed(handle, account)` | Is there a persistent grant? | | `globalAllowed(handle)` | Is the handle globally allowed? | | `isAllowedForDecryption(handle)` | Is the handle on the decryption allowlist? | -| isAllowedWithPermission | Does this EIP-712 [permit](/client-sdk/guides/permits) authorize its issuer for the given handle? | +| isAllowedWithPermission | Does this permit (ACP) authorize its issuer for the given handle? | The last two are what the decryption path runs on. For every `decrypt` or `sealoutput` request, Teecryptor queries the ACL through the TaskManager: `isAllowedWithPermission` when a permit is attached, or `isPubliclyAllowed` (the TaskManager's wrapper over `globalAllowed`) when none is. A future [Threshold Network](/deep-dive/research/future-plans) will consume the same interface. From 89f2200d1cbbf339a88ce076c7051d7225e36050 Mon Sep 17 00:00:00 2001 From: haim Date: Mon, 24 Aug 2026 11:20:06 +0300 Subject: [PATCH 34/58] [DOCS] deep-dive/teecryptor: permit travels as acp, sealoutput requires one (ACP upgrade) --- deep-dive/cofhe-components/teecryptor.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deep-dive/cofhe-components/teecryptor.mdx b/deep-dive/cofhe-components/teecryptor.mdx index 4827d50..aa5a4bd 100644 --- a/deep-dive/cofhe-components/teecryptor.mdx +++ b/deep-dive/cofhe-components/teecryptor.mdx @@ -13,7 +13,7 @@ Teecryptor is the component that decrypts CoFHE ciphertexts. It holds the FHE se ## How a decrypt request is processed -Every `decrypt` and `sealoutput` request carries a ciphertext handle, a host chain id, and optionally a [permit](/client-sdk/guides/permits). Teecryptor then runs a fixed pipeline: +Every `decrypt` and `sealoutput` request carries a ciphertext handle, a host chain id, and optionally a [permit](/client-sdk/guides/permits), sent on the wire as an `acp` (Access Control Permission). A `sealoutput` request requires one, since the ACP carries the sealing key. Teecryptor then runs a fixed pipeline: @@ -52,7 +52,7 @@ sequenceDiagram participant Registry as CommitmentRegistry participant Store as CT Server - SDK->>Teecryptor: decrypt / sealoutput (handle, chain id, permit?) + SDK->>Teecryptor: decrypt / sealoutput (handle, chain id, acp?) par Authorization Teecryptor->>TaskManager: isAllowedWithPermission / isPubliclyAllowed TaskManager-->>Teecryptor: allowed From a90032a7df8f0596ddbe251893d6ee8acaf2f99a Mon Sep 17 00:00:00 2001 From: haim Date: Mon, 24 Aug 2026 11:20:07 +0300 Subject: [PATCH 35/58] [DOCS] deep-dive/decryption-request-flow: define permit as ACP at first use (ACP upgrade) --- deep-dive/data-flows/decryption-request-flow.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deep-dive/data-flows/decryption-request-flow.mdx b/deep-dive/data-flows/decryption-request-flow.mdx index 3c40906..45b5613 100644 --- a/deep-dive/data-flows/decryption-request-flow.mdx +++ b/deep-dive/data-flows/decryption-request-flow.mdx @@ -13,7 +13,7 @@ Decryption in CoFHE is SDK-driven and happens offchain, inside [Teecryptor](/dee There are two SDK entry points, one per destination: - **`decryptForTx`**: returns the plaintext with a Teecryptor signature you can publish onchain. Guide: [Decrypt to Tx](/client-sdk/guides/decrypt-to-tx). -- **`decryptForView`**: returns the plaintext sealed to your [permit](/client-sdk/guides/permits), for UI display and offchain reads. Guide: [Decrypt to View](/client-sdk/guides/decrypt-to-view). +- **`decryptForView`**: returns the plaintext sealed to your [permit](/client-sdk/guides/permits) (an ACP, Access Control Permission, onchain), for UI display and offchain reads. Guide: [Decrypt to View](/client-sdk/guides/decrypt-to-view). A freshly computed handle may not be decryptable immediately: its ciphertext and commitment land shortly after the transaction. Until then Teecryptor answers with a retryable status and the SDK re-submits automatically. @@ -97,7 +97,7 @@ sequenceDiagram participant Chain as Host chain App->>SDK: decryptForTx / decryptForView (ctHash) - SDK->>Teecryptor: decrypt or sealoutput request (handle, chain id, permit?) + SDK->>Teecryptor: decrypt or sealoutput request (handle, chain id, acp?) Teecryptor->>Chain: ACL check (isAllowedWithPermission / isPubliclyAllowed) Teecryptor->>Teecryptor: verify commitment, decrypt in enclave alt decryptForTx From c9d9f9ef5ce7e3a5c67a77193fe31ff5b1b286b9 Mon Sep 17 00:00:00 2001 From: haim Date: Mon, 24 Aug 2026 11:20:46 +0300 Subject: [PATCH 36/58] [DOCS] deep-dive/zk-verifier: batch verification with contract-bound digest (ACP upgrade) --- deep-dive/cofhe-components/zk-verifier.mdx | 23 +++++++++++----------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/deep-dive/cofhe-components/zk-verifier.mdx b/deep-dive/cofhe-components/zk-verifier.mdx index ce41272..88ec7a1 100644 --- a/deep-dive/cofhe-components/zk-verifier.mdx +++ b/deep-dive/cofhe-components/zk-verifier.mdx @@ -9,7 +9,7 @@ description: "Offchain service that verifies user inputs using Zero-Knowledge Pr | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Type** | Offchain service running inside a hardware-attested TEE. | | **Function** | Verifies the user's input, ensuring that it is safe to use. | -| **Responsibilities** | β€’ Receives users' ZKPoKs for their inputs.
β€’ Verifies those proofs.
β€’ Signs an approval the user passes with the inputs to the contract.
β€’ Stores the verified ciphertext bytes. | +| **Responsibilities** | β€’ Receives users' ZKPoKs for their input batches.
β€’ Verifies those proofs.
β€’ Signs one approval per verified batch.
β€’ Stores the verified ciphertext bytes. | ## Why ZKPoK? @@ -34,11 +34,11 @@ When providing ciphertexts as an input to a smart contract, users have to genera The process of sending inputs to a smart contract: 1. The user encrypts the inputs and generates a ZK proof of knowledge for them. -2. The user sends the ciphertexts and proofs to the ZK Verifier. -3. The ZK Verifier verifies each proof. If valid, it signs a message that approves the input. -4. The ZK Verifier returns the signed approval to the user. -5. The user sends `(ciphertext, signed_approve)` pairs as inputs to a contract call. -6. The contract verifies the signed message, approving the inputs. This also emits `InputVerified`, which anchors a commitment for the input so it becomes decryptable later. +2. The user sends the ciphertexts and proofs to the ZK Verifier, as one batch. +3. The ZK Verifier verifies each proof. If all are valid, it signs one message approving the whole batch. +4. The ZK Verifier returns the handles and the batch approval to the user. +5. The user sends the handles and the approval as inputs to a contract call. +6. The contract verifies the batch signature, approving the inputs and emitting `InputVerified` per input, which anchors a commitment so each input becomes decryptable later. 7. The contract performs the actual logic. Most of this process is abstracted away. Steps 1 to 6 all happen behind the SDK and library calls, while step 7 (the actual logic) is up to you to write. @@ -51,13 +51,12 @@ The signed message is verified onchain by the TaskManager using `ecrecover`; the ## Signature format -For developers integrating without the SDK, the signed pre-image is: +For developers integrating without the SDK, the signature covers a batch digest. Each input is hashed, the hashes are concatenated in input order, and the digest of that concatenation is signed: ```text -message_to_sign = keccak256( - ct_hash (32 bytes) || ct_type (1 byte) || security_zone (1 byte) - || account_addr (20 bytes, the sender's address) || chain_id (32 bytes, big-endian) -) +h_i = keccak256(ct_hash (32 bytes) || utype (1 byte) || security_zone (1 byte) + || sender (20 bytes) || chain_id (32 bytes, big-endian) || consuming_contract (20 bytes)) +digest = keccak256(h_0 || h_1 || ... || h_n) ``` -The `recid` value the service returns (0 or 1) must be adjusted to 27 or 28 for Solidity's `ecrecover`. +The digest binds the sender and the consuming contract, so a verified batch cannot be replayed by another account or into another contract. The `recid` value the service returns (0 or 1) must be adjusted to 27 or 28 for Solidity's `ecrecover`. From 27c224875b9a5ffabee07528a4553a42e2d433be Mon Sep 17 00:00:00 2001 From: haim Date: Mon, 24 Aug 2026 13:42:55 +0300 Subject: [PATCH 37/58] [DOCS] deep-dive/key-management: new page for the key ceremony, partner custody and attested release --- deep-dive/cofhe-components/key-management.mdx | 48 +++++++++++++++++++ docs.json | 3 +- 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 deep-dive/cofhe-components/key-management.mdx diff --git a/deep-dive/cofhe-components/key-management.mdx b/deep-dive/cofhe-components/key-management.mdx new file mode 100644 index 0000000..ed478ff --- /dev/null +++ b/deep-dive/cofhe-components/key-management.mdx @@ -0,0 +1,48 @@ +--- +title: Key Management +description: "How CoFHE's keys are created in an attested ceremony, split among independent partners, and released only to attested enclaves" +--- + +CoFHE's security rests on a small set of keys, and none of them is ever held whole by any person or machine outside an attested enclave. + +| Key | Used by | Purpose | +|-----|---------|---------| +| FHE network key | [Teecryptor](/deep-dive/cofhe-components/teecryptor) | Decrypts ciphertexts inside the enclave | +| Result-signing key | Teecryptor | Signs decrypt results the TaskManager verifies onchain | +| Verifier signing key | [ZK Verifier](/deep-dive/cofhe-components/zk-verifier) | Signs verified input batches | +| Public material | Everyone | The network public key and CRS that clients encrypt against | + +## The ceremony + +The keys are born inside a TEE. A one-shot key-generation service runs in its own hardware-attested enclave and generates the network keyset there. The secret material is split with Shamir secret sharing into six shares; any three reconstruct it (3-of-6). + +Each share goes to one **partner**: an independent custodian with its own share store. A partner's store accepts writes only from the attested ceremony image, so nobody can slip in a substitute share. The public material is published for clients. The ceremony enclave then terminates; the assembled key is never persisted anywhere. + +```mermaid +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220, "actorFontSize": 16, "messageFontSize": 16, "noteFontSize": 15}}}%% +sequenceDiagram + participant Ceremony as Keygen ceremony (TEE) + participant Partners as Partners (custodians) + participant Pub as Public material + participant Enclave as Service enclave + + Note over Ceremony: generates the keyset in-enclave,
splits secrets with Shamir (3-of-6) + Ceremony->>Partners: one encrypted share per partner (attested write) + Ceremony->>Pub: publish public material + Note over Ceremony: terminates, whole key
never persisted + Note over Partners,Enclave: later, at every service boot + Enclave->>Partners: attestation of the running image + Note over Partners: each partner verifies independently + Partners-->>Enclave: release share, only to the approved image + Note over Enclave: reconstruct in memory,
zeroize transit material +``` + +## Custody + +At rest, the key exists only as shares held by independent partners. No partner can reconstruct anything alone, and no quorum below the threshold can either. Fhenix operates the services, but it cannot assemble the key outside an attested enclave any more than anyone else can. + +## Release at boot + +When Teecryptor or the ZK Verifier starts, the TEE hardware produces an attestation of the exact code image it is running. Each partner independently verifies that attestation and releases its share only to the approved image digest. The enclave reconstructs the key in memory, zeroizes the transit material, and never persists it. Restarting the service repeats the whole handshake. + +The guarantee this chain yields: from generation through every reconstruction, the key exists only inside hardware-attested enclaves running reviewed code. diff --git a/docs.json b/docs.json index be9b785..62a2df4 100644 --- a/docs.json +++ b/docs.json @@ -244,7 +244,8 @@ "deep-dive/cofhe-components/zk-verifier", "deep-dive/cofhe-components/fheos-server", "deep-dive/cofhe-components/fhe-engine", - "deep-dive/cofhe-components/teecryptor" + "deep-dive/cofhe-components/teecryptor", + "deep-dive/cofhe-components/key-management" ] }, { From 7b0511474dbf6520e1081a572824e96caa650469 Mon Sep 17 00:00:00 2001 From: haim Date: Mon, 24 Aug 2026 13:42:55 +0300 Subject: [PATCH 38/58] [DOCS] deep-dive: partners in the overview architecture, key-management links from teecryptor and zk-verifier --- deep-dive/cofhe-components/overview.mdx | 5 +++++ deep-dive/cofhe-components/teecryptor.mdx | 2 +- deep-dive/cofhe-components/zk-verifier.mdx | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index f61701c..f69b5dc 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -32,6 +32,8 @@ flowchart TB CR["CommitmentRegistry"] end + PRT["Partners (key custodians)"] + SDK -- "encrypt input + ZK proof" --> ZK ZK -- "store ciphertext" --> CTS FHEC --> TM @@ -46,6 +48,8 @@ flowchart TB TEE -- "verify commitment" --> CR SDK -- "publish signed result" --> TM TM --> PS + PRT -- "release key shares (attested)" --> TEE + PRT -- "release signing key (attested)" --> ZK ``` ## The onchain contracts @@ -66,6 +70,7 @@ flowchart TB - **CT Server**: the ciphertext store. It holds the ciphertext bytes and serves them to the other services. - **Blockchain Poster**: batches result commitments and posts them to the CommitmentRegistry. - **[Teecryptor](/deep-dive/cofhe-components/teecryptor)**: the decryption service. It runs inside a hardware-attested TEE, authorizes every request against the onchain ACL, verifies the ciphertext commitment, and returns signed or sealed results. +- **Partners**: independent custodians of the key material. Each holds a Shamir share and releases it only to an attested enclave. See [Key Management](/deep-dive/cofhe-components/key-management). Services communicate through message queues rather than direct calls, so each stage can retry and scale independently. diff --git a/deep-dive/cofhe-components/teecryptor.mdx b/deep-dive/cofhe-components/teecryptor.mdx index aa5a4bd..28a6813 100644 --- a/deep-dive/cofhe-components/teecryptor.mdx +++ b/deep-dive/cofhe-components/teecryptor.mdx @@ -73,7 +73,7 @@ Remote attestation is what turns "trust the operator" into "verify the code". Be ## Key custody -The FHE secret key is never stored whole. It is split with Shamir secret sharing into six shares held by independent parties, with any three required for reconstruction (3-of-6). At boot, the attested enclave collects shares from the custodians, reconstructs the key in memory, and zeroizes the transient share material. The reconstructed key exists only inside the enclave for the lifetime of the process. It is never persisted. The result-signing key travels inside the same split secret, so it too can only materialize inside the attested enclave. +The FHE secret key is never stored whole. It is split with Shamir secret sharing into six shares held by independent parties, with any three required for reconstruction (3-of-6). At boot, the attested enclave collects shares from the custodians, reconstructs the key in memory, and zeroizes the transient share material. The reconstructed key exists only inside the enclave for the lifetime of the process. It is never persisted. The result-signing key travels inside the same split secret, so it too can only materialize inside the attested enclave. See [Key Management](/deep-dive/cofhe-components/key-management) for the ceremony that creates and distributes the shares. ## Result signing diff --git a/deep-dive/cofhe-components/zk-verifier.mdx b/deep-dive/cofhe-components/zk-verifier.mdx index 88ec7a1..0a67674 100644 --- a/deep-dive/cofhe-components/zk-verifier.mdx +++ b/deep-dive/cofhe-components/zk-verifier.mdx @@ -45,7 +45,7 @@ Most of this process is abstracted away. Steps 1 to 6 all happen behind the SDK ## Trust model -The ZK Verifier runs inside a hardware-attested TEE (Intel TDX). Its signing key is released only to the exact attested code image, so neither the operator nor anyone else can sign approvals outside the reviewed program. After a successful verification, the service stores the ciphertext bytes in the CT Server and archives the inputs and proofs for auditability. +The ZK Verifier runs inside a hardware-attested TEE (Intel TDX). Its signing key is held as Shamir shares by independent partners and released only to the exact attested code image. Neither the operator nor anyone else can sign approvals outside the reviewed program. See [Key Management](/deep-dive/cofhe-components/key-management) for how shares are created and released. After a successful verification, the service stores the ciphertext bytes in the CT Server and archives the inputs and proofs for auditability. The signed message is verified onchain by the TaskManager using `ecrecover`; the verifier's signer address is registered there as `verifierSigner`. From 4b0c061812e3969143c97a112ee4c7ea25da8e28 Mon Sep 17 00:00:00 2001 From: haim Date: Mon, 24 Aug 2026 14:14:19 +0300 Subject: [PATCH 39/58] [DOCS] deep-dive/overview: rearranged architecture diagram with color-coded flows, CT Server as the database gate --- deep-dive/cofhe-components/overview.mdx | 36 ++++++++++--------- .../data-flows/fhe-operation-request-flow.mdx | 2 +- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index f69b5dc..6fdc8ee 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -8,48 +8,52 @@ CoFHE (Coprocessor for Fully Homomorphic Encryption) lets smart contracts comput ```mermaid %%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220, "actorFontSize": 16, "messageFontSize": 16, "noteFontSize": 15}}}%% flowchart TB + PRT["Partners (key custodians)"] + subgraph App["Application"] SDK["Client SDK"] end - subgraph Host["Host chain"] - FHEC["Your contract + FHE.sol"] - TM["TaskManager + ACL"] - PS["PlaintextsStorage"] - end - subgraph CoFHE["CoFHE services (offchain)"] ZK["ZK Verifier"] CTS["CT Server"] + TEE["Teecryptor (TEE)"] SL["Slim Listener"] FheOS["FheOS Server"] Engine["FHE Engine"] BP["Blockchain Poster"] - TEE["Teecryptor (TEE)"] + end + + subgraph Host["Host chain"] + FHEC["Your contract + FHE.sol"] + TM["TaskManager + ACL"] + PS["PlaintextsStorage"] end subgraph Registry["Registry chain"] CR["CommitmentRegistry"] end - PRT["Partners (key custodians)"] - - SDK -- "encrypt input + ZK proof" --> ZK + SDK -- "encrypt inputs" --> ZK ZK -- "store ciphertext" --> CTS FHEC --> TM TM -- "task events" --> SL SL --> FheOS FheOS --> Engine - Engine -- "result commitments" --> BP + Engine -- "commitments" --> BP BP --> CR - SDK -- "decrypt / sealoutput" --> TEE + SDK -- "decrypt" --> TEE TEE -- "ACL check" --> TM TEE -- "fetch ciphertext" --> CTS TEE -- "verify commitment" --> CR - SDK -- "publish signed result" --> TM + SDK -- "publish result" --> TM TM --> PS - PRT -- "release key shares (attested)" --> TEE - PRT -- "release signing key (attested)" --> ZK + PRT -- "key shares (attested)" --> TEE + PRT -- "signing key (attested)" --> ZK + + linkStyle 0,1 stroke:#7FDB8F + linkStyle 8,9,10,11,12,13 stroke:#0AD9DC + linkStyle 14,15 stroke:#E0C36A ``` ## The onchain contracts @@ -67,7 +71,7 @@ flowchart TB - **[Slim Listener](/deep-dive/cofhe-components/slim-listener)**: watches TaskManager events on each host chain and forwards them into the coprocessor's queues. - **[FheOS Server](/deep-dive/cofhe-components/fheos-server)**: ingests task events, verifies inputs, creates result placeholders, and routes work to the FHE Engine. It does not execute FHE operations itself. - **[FHE Engine](/deep-dive/cofhe-components/fhe-engine)**: executes every FHE operation on encrypted data, persists the resulting ciphertexts, and emits a commitment for each result. -- **CT Server**: the ciphertext store. It holds the ciphertext bytes and serves them to the other services. +- **CT Server**: the gate to the ciphertext database. Every ciphertext read and write for the other services goes through it. - **Blockchain Poster**: batches result commitments and posts them to the CommitmentRegistry. - **[Teecryptor](/deep-dive/cofhe-components/teecryptor)**: the decryption service. It runs inside a hardware-attested TEE, authorizes every request against the onchain ACL, verifies the ciphertext commitment, and returns signed or sealed results. - **Partners**: independent custodians of the key material. Each holds a Shamir share and releases it only to an attested enclave. See [Key Management](/deep-dive/cofhe-components/key-management). diff --git a/deep-dive/data-flows/fhe-operation-request-flow.mdx b/deep-dive/data-flows/fhe-operation-request-flow.mdx index e93ed51..e9d4004 100644 --- a/deep-dive/data-flows/fhe-operation-request-flow.mdx +++ b/deep-dive/data-flows/fhe-operation-request-flow.mdx @@ -99,7 +99,7 @@ The FheOS Server consumes `blockchain-events`, validates the task, and routes FH The FHE Engine consumes `engine-requests` and: 1. Executes the requested operation on the encrypted data. -2. Stores the result ciphertext in the coprocessor's store, keyed by the handle. +2. Stores the result ciphertext in the ciphertext database, keyed by the handle. 3. Releases any dependent operations that were deferred while waiting for this result. 4. Publishes a commitment for the result (the hash of the stored ciphertext bytes) to the `commitment-requests` queue.
From 0978b9c325455a7a5287ab33da34651e2e5ebf81 Mon Sep 17 00:00:00 2001 From: haim Date: Mon, 24 Aug 2026 14:46:20 +0300 Subject: [PATCH 40/58] [DOCS] deep-dive/overview: group TEEs and cluster services inside the diagram, partners beside the TEEs --- deep-dive/cofhe-components/overview.mdx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index 6fdc8ee..a84023d 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -15,13 +15,17 @@ flowchart TB end subgraph CoFHE["CoFHE services (offchain)"] - ZK["ZK Verifier"] - CTS["CT Server"] - TEE["Teecryptor (TEE)"] - SL["Slim Listener"] - FheOS["FheOS Server"] - Engine["FHE Engine"] - BP["Blockchain Poster"] + subgraph TEES[" "] + ZK["ZK Verifier"] + TEE["Teecryptor (TEE)"] + end + subgraph K8S[" "] + SL["Slim Listener"] + FheOS["FheOS Server"] + Engine["FHE Engine"] + BP["Blockchain Poster"] + CTS["CT Server"] + end end subgraph Host["Host chain"] From 0137fe1cdcaacc6141502b69b1d82541e8be6f75 Mon Sep 17 00:00:00 2001 From: haim Date: Mon, 24 Aug 2026 15:57:57 +0300 Subject: [PATCH 41/58] [DOCS] deep-dive/overview: Teecryptor first, CT Server near the enclaves, horizontal service chain at the bottom --- deep-dive/cofhe-components/overview.mdx | 27 ++++++++++--------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index a84023d..e313cd6 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -16,15 +16,13 @@ flowchart TB subgraph CoFHE["CoFHE services (offchain)"] subgraph TEES[" "] - ZK["ZK Verifier"] TEE["Teecryptor (TEE)"] + ZK["ZK Verifier"] end + CTS["CT Server"] subgraph K8S[" "] - SL["Slim Listener"] - FheOS["FheOS Server"] - Engine["FHE Engine"] - BP["Blockchain Poster"] - CTS["CT Server"] + direction LR + SL["Slim Listener"] --> FheOS["FheOS Server"] --> Engine["FHE Engine"] -- "commitments" --> BP["Blockchain Poster"] end end @@ -38,25 +36,22 @@ flowchart TB CR["CommitmentRegistry"] end - SDK -- "encrypt inputs" --> ZK - ZK -- "store ciphertext" --> CTS - FHEC --> TM - TM -- "task events" --> SL - SL --> FheOS - FheOS --> Engine - Engine -- "commitments" --> BP - BP --> CR SDK -- "decrypt" --> TEE TEE -- "ACL check" --> TM TEE -- "fetch ciphertext" --> CTS TEE -- "verify commitment" --> CR + SDK -- "encrypt inputs" --> ZK + ZK -- "store ciphertext" --> CTS + FHEC --> TM + TM -- "task events" --> K8S + K8S -- "post commitments" --> CR SDK -- "publish result" --> TM TM --> PS PRT -- "key shares (attested)" --> TEE PRT -- "signing key (attested)" --> ZK - linkStyle 0,1 stroke:#7FDB8F - linkStyle 8,9,10,11,12,13 stroke:#0AD9DC + linkStyle 7,8 stroke:#7FDB8F + linkStyle 3,4,5,6,12,13 stroke:#0AD9DC linkStyle 14,15 stroke:#E0C36A ``` From e6cfe1843ee7e42aafda0387ed1dc3ab4b48f92b Mon Sep 17 00:00:00 2001 From: haim Date: Thu, 27 Aug 2026 16:07:21 +0300 Subject: [PATCH 42/58] [DOCS] cofhe-components/overview: offchain components retitle, current-state ZK Verifier bullet, drop flow word --- deep-dive/cofhe-components/overview.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index e313cd6..dd56daa 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -63,10 +63,10 @@ flowchart TB - **[PlaintextsStorage](/deep-dive/cofhe-components/plaintext-storage)**: stores decrypted results after they are published onchain with a verified Teecryptor signature. - **[CommitmentRegistry](/deep-dive/cofhe-components/commitment-registry)**: lives on a dedicated registry chain and records a hash commitment for every ciphertext the coprocessor produces or verifies. Teecryptor checks it before decrypting anything. -## The offchain services +## The offchain components - **[Client SDK](/client-sdk/introduction/overview)** (`@cofhe/sdk`): the TypeScript library applications use to encrypt inputs, manage [permits](/client-sdk/guides/permits), and decrypt outputs. -- **[ZK Verifier](/deep-dive/cofhe-components/zk-verifier)**: verifies the zero-knowledge proof attached to every encrypted input, signs it, and stores the ciphertext bytes. +- **[ZK Verifier](/deep-dive/cofhe-components/zk-verifier)**: a standalone service that verifies encrypted inputs in batches. It checks each zero-knowledge proof, stores the ciphertexts, and signs one approval for the whole batch. - **[Slim Listener](/deep-dive/cofhe-components/slim-listener)**: watches TaskManager events on each host chain and forwards them into the coprocessor's queues. - **[FheOS Server](/deep-dive/cofhe-components/fheos-server)**: ingests task events, verifies inputs, creates result placeholders, and routes work to the FHE Engine. It does not execute FHE operations itself. - **[FHE Engine](/deep-dive/cofhe-components/fhe-engine)**: executes every FHE operation on encrypted data, persists the resulting ciphertexts, and emits a commitment for each result. @@ -80,7 +80,7 @@ Services communicate through message queues rather than direct calls, so each st ## Data flows 1. **[Encryption request](/deep-dive/data-flows/encryption-request-flow)**: an input is encrypted client-side and proven valid with a zero-knowledge proof before it enters the chain. -2. **[FHE operation flow](/deep-dive/data-flows/fhe-operation-request-flow)**: a contract requests a computation; the coprocessor executes it and commits to the result. +2. **[FHE operation](/deep-dive/data-flows/fhe-operation-request-flow)**: a contract requests a computation; the coprocessor executes it and commits to the result. 3. **[Decryption](/deep-dive/data-flows/decryption-request-flow)**: the SDK asks Teecryptor to decrypt a handle, either as a signed plaintext for onchain publication or sealed to a permit for offchain reads. ## Future plans From cea8b2a54423b29c98bf176fba7e57413e7ebbc4 Mon Sep 17 00:00:00 2001 From: haim Date: Thu, 27 Aug 2026 16:07:21 +0300 Subject: [PATCH 43/58] [DOCS] cofhe-components/zk-verifier: verifier stores the encrypted values before signing the batch approval --- deep-dive/cofhe-components/zk-verifier.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deep-dive/cofhe-components/zk-verifier.mdx b/deep-dive/cofhe-components/zk-verifier.mdx index 0a67674..2d7b883 100644 --- a/deep-dive/cofhe-components/zk-verifier.mdx +++ b/deep-dive/cofhe-components/zk-verifier.mdx @@ -35,7 +35,7 @@ The process of sending inputs to a smart contract: 1. The user encrypts the inputs and generates a ZK proof of knowledge for them. 2. The user sends the ciphertexts and proofs to the ZK Verifier, as one batch. -3. The ZK Verifier verifies each proof. If all are valid, it signs one message approving the whole batch. +3. The ZK Verifier verifies each proof. If all are valid, it stores the encrypted values in the ciphertext database and signs one message approving the whole batch. 4. The ZK Verifier returns the handles and the batch approval to the user. 5. The user sends the handles and the approval as inputs to a contract call. 6. The contract verifies the batch signature, approving the inputs and emitting `InputVerified` per input, which anchors a commitment so each input becomes decryptable later. From a58278df7809877134eb6915a4d2204e08715c24 Mon Sep 17 00:00:00 2001 From: haim Date: Thu, 27 Aug 2026 16:07:21 +0300 Subject: [PATCH 44/58] [DOCS] cofhe-components/commitment-registry: define what a commitment is before why, remove private-repo links --- deep-dive/cofhe-components/commitment-registry.mdx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/deep-dive/cofhe-components/commitment-registry.mdx b/deep-dive/cofhe-components/commitment-registry.mdx index 6e38156..045be8f 100644 --- a/deep-dive/cofhe-components/commitment-registry.mdx +++ b/deep-dive/cofhe-components/commitment-registry.mdx @@ -10,6 +10,10 @@ description: "Registry-chain contract that records FHE computation commitments. | **Responsibilities** | β€’ Provide an authoritative source of ciphertext integrity that [Teecryptor](/deep-dive/cofhe-components/teecryptor) checks **before** decrypting.
β€’ Group commitments by an opaque `version` tag so a future tfhe-rs / FHE-parameter upgrade can roll out without invalidating earlier ciphertexts.
β€’ Enforce write-once semantics per `(version, handle)` to prevent commitment replacement.
β€’ Expose paginated enumeration so offchain tooling can audit what has been posted. | | **Deployment** | One deployment per registry chain, behind an ERC-1967 proxy. | +## What a commitment is + +A commitment is the `keccak256` hash of a ciphertext's canonical stored bytes. The [FHE Engine](/deep-dive/cofhe-components/fhe-engine) produces one for every result it computes, and the coprocessor anchors one for every encrypted input it verifies. The Blockchain Poster batches them and writes them to this registry. + ## Why commitments? The commitment is a safety check in the decryption flow. Before decrypting anything, [Teecryptor](/deep-dive/cofhe-components/teecryptor) confirms that the ciphertext bytes it fetched hash to the commitment anchored onchain. It only ever decrypts a ciphertext the coprocessor actually produced, never a tampered or substituted one. @@ -29,7 +33,7 @@ mapping(address => bool) poster ## Version lifecycle -`version` is an opaque `bytes32` tag chosen by the coprocessor when FHE parameters change, currently the ASCII tag `"2"` (see [the `COMMITMENT_VERSION` changelog notes](https://github.com/FhenixProtocol/cofhe/blob/master/CHANGELOG.md#060---2026-05-05)). Every version moves through a small state machine: +`version` is an opaque `bytes32` tag chosen by the coprocessor when FHE parameters change, currently the ASCII tag `"2"`. Every version moves through a small state machine: ```mermaid %%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220, "actorFontSize": 16, "messageFontSize": 16, "noteFontSize": 15}}}%% @@ -52,7 +56,7 @@ The admin-only `setVersionStatus(version, newStatus)` enforces these transitions ## Write surface -Only accounts holding the **poster** role can write commitments (`postCommitments`, `postCommitmentsSafe`); posts from anyone else revert with `OnlyPosterAllowed(caller)`. Poster management and version transitions are admin-only. In production, the poster role is held by the [`blockchain-poster`](https://github.com/FhenixProtocol/cofhe/tree/master/src/services/blockchain-poster) service's relayer signer (OpenZeppelin Relayer). +Only accounts holding the **poster** role can write commitments (`postCommitments`, `postCommitmentsSafe`); posts from anyone else revert with `OnlyPosterAllowed(caller)`. Poster management and version transitions are admin-only. In production, the poster role is held by the Blockchain Poster service's relayer signer (OpenZeppelin Relayer). ## Writing commitments @@ -112,5 +116,3 @@ The paginated `getHandles` is the recommended way to enumerate a version: `getSi ## Source - Solidity: [`contracts/internal/registry-chain/contracts/commitment-registry/CommitmentRegistry.sol`](https://github.com/FhenixProtocol/cofhe-contracts/blob/master/contracts/internal/registry-chain/contracts/commitment-registry/CommitmentRegistry.sol). -- Offchain poster service: [`src/services/blockchain-poster/`](https://github.com/FhenixProtocol/cofhe/tree/master/src/services/blockchain-poster), introduced in [cofhe `0.6.0`](https://github.com/FhenixProtocol/cofhe/blob/master/CHANGELOG.md#060---2026-05-05). -- FHE Engine commitment-version bumping: [`fhe-engine/src/rabbitmq/handlers.rs`](https://github.com/FhenixProtocol/cofhe/blob/master/fhe-engine/src/rabbitmq/handlers.rs). From d8e3eba1a19641696900c4eb901a25189b9c40bb Mon Sep 17 00:00:00 2001 From: haim Date: Thu, 27 Aug 2026 16:07:21 +0300 Subject: [PATCH 45/58] [DOCS] STYLE: no links to private repositories --- STYLE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/STYLE.md b/STYLE.md index 40111a1..1a82c62 100644 --- a/STYLE.md +++ b/STYLE.md @@ -100,6 +100,7 @@ Do not use internal names in public docs: no hostnames, no GCP project names, no - Internal links use root-relative paths: `/fhe-library/core-concepts/access-control`, not `../core-concepts/access-control` and not the full `https://cofhe-docs.fhenix.zone/...` URL. Relative paths break when a page moves; absolute URLs break preview deployments. - Link text describes the destination. "See [access control](/fhe-library/core-concepts/access-control)", never `"click [here](/...)"` or a bare URL. +- Never link to a private repository; readers get a 404. Of the FhenixProtocol repos, only `cofhe-contracts` and `cofhesdk` are public. Name a component or path in prose instead, and add the link when the repo goes public. - Every image is wrapped in `` and carries alt text that says what the image shows, not what it is called. "Sealed output flowing from the FHE Engine to the client", not "diagram". - Pick the component that matches the content, and use each one for one job: From e67b6420699949783bcb87b040a59d4726e86e3e Mon Sep 17 00:00:00 2001 From: haim Date: Thu, 27 Aug 2026 17:47:09 +0300 Subject: [PATCH 46/58] [DOCS] cofhe-components/fhe-engine: merge listener, fheos, and poster stages into one pipeline page --- deep-dive/cofhe-components/fhe-engine.mdx | 32 +++++++++++++++++------ 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/deep-dive/cofhe-components/fhe-engine.mdx b/deep-dive/cofhe-components/fhe-engine.mdx index 413477f..66660cf 100644 --- a/deep-dive/cofhe-components/fhe-engine.mdx +++ b/deep-dive/cofhe-components/fhe-engine.mdx @@ -1,21 +1,37 @@ --- title: FHE Engine -description: "Offchain execution service that runs every FHE operation and commits to its results" +description: "The offchain execution pipeline that carries a task from onchain event to committed result" --- | Aspect | Description | |---------|-------------| -| **Type** | Offchain execution service. | -| **Function** | Executes every FHE operation and persists the encrypted results. | -| **Responsibilities** | β€’ Consumes validated work from `engine-requests`
β€’ Executes the operation with the TFHE library
β€’ Stores each result ciphertext by handle
β€’ Publishes a hash commitment for every result | +| **Type** | Offchain execution pipeline. | +| **Function** | Carries every FHE task from onchain event to committed result. | +| **Responsibilities** | β€’ Listens to TaskManager events on each host chain
β€’ Validates and orders operations
β€’ Executes them with the TFHE library
β€’ Stores results and posts a commitment for each | -The FHE Engine is where computation actually happens. It consumes the work the [FheOS Server](/deep-dive/cofhe-components/fheos-server) validated and runs the requested operation (arithmetic, comparison, select, cast, random) on the encrypted operands. The result ciphertext is stored under the handle the TaskManager issued, and operations that were waiting on that handle are released as soon as it lands. +The FHE Engine is the computation side of CoFHE. Contracts never call it; it subscribes to what happens onchain, does the encrypted math, and anchors the results. From the outside it is one component with four stages. -FHE operations are computationally heavy, so the engine bounds how many run concurrently and scales horizontally behind the queue. Backpressure lives in the queue, not in dropped work. +```mermaid +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}}}%% +flowchart LR + TM["TaskManager events"] --> L["Listen"] --> V["Validate and order"] --> X["Execute"] --> C["Commit"] --> CR["CommitmentRegistry"] +``` -## Result commitments +## Listen -For every stored result, the engine publishes a commitment (the keccak256 hash of the stored ciphertext bytes) to the `commitment-requests` queue. The Blockchain Poster batches these and posts them to the [CommitmentRegistry](/deep-dive/cofhe-components/commitment-registry). This is the anchor [Teecryptor](/deep-dive/cofhe-components/teecryptor) verifies before decrypting anything: only bytes that hash to a registered commitment ever reach the decryption key. +The engine watches TaskManager events on every host chain it serves. `TaskCreated` events bring FHE operations in for execution; `InputVerified` events bring verified encrypted inputs in so a commitment gets anchored for each. Delivery is reliable by construction. The listener tracks the last processed block, so a crash or a missed range is re-scanned rather than skipped. + +## Validate and order + +Before anything executes, the engine checks that each operation is well formed and that the inputs it references exist. Operations can arrive before the inputs they depend on have finished computing. Such operations are deferred and released once the missing results land, so out-of-order arrival never produces a wrong answer. Work that is malformed, or that references inputs that never materialize, is set aside for inspection instead of being silently dropped. + +## Execute + +Validated operations run against the TFHE library: arithmetic, comparison, select, cast, and random generation on encrypted operands. The result ciphertext is stored under the handle the TaskManager issued, and any deferred operations waiting on that handle are released as soon as it lands. + +## Commit + +For every stored result, the engine produces a commitment, the `keccak256` hash of the stored ciphertext bytes. Commitments are batched and posted to the [CommitmentRegistry](/deep-dive/cofhe-components/commitment-registry) on the registry chain. This is the anchor [Teecryptor](/deep-dive/cofhe-components/teecryptor) verifies before decrypting anything: only bytes that hash to a registered commitment ever reach the decryption key. ## Key material From 6ac7cef04fac173e1cd5e3043c9cd75f2653302f Mon Sep 17 00:00:00 2001 From: haim Date: Thu, 27 Aug 2026 17:47:09 +0300 Subject: [PATCH 47/58] [DOCS] cofhe-components: remove slim-listener and fheos-server pages, redirect both to fhe-engine --- deep-dive/cofhe-components/fheos-server.mdx | 20 -------------------- deep-dive/cofhe-components/slim-listener.mdx | 19 ------------------- docs.json | 10 ++++++++-- 3 files changed, 8 insertions(+), 41 deletions(-) delete mode 100644 deep-dive/cofhe-components/fheos-server.mdx delete mode 100644 deep-dive/cofhe-components/slim-listener.mdx diff --git a/deep-dive/cofhe-components/fheos-server.mdx b/deep-dive/cofhe-components/fheos-server.mdx deleted file mode 100644 index bbf7228..0000000 --- a/deep-dive/cofhe-components/fheos-server.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: FheOS Server -description: "Offchain ingestion service that validates task events and orchestrates work for the FHE Engine" ---- - -| Aspect | Description | -|---------|-------------| -| **Type** | Offchain ingestion and orchestration service. | -| **Function** | Validates task events and routes work to the [FHE Engine](/deep-dive/cofhe-components/fhe-engine). | -| **Responsibilities** | β€’ Consumes task events from the `blockchain-events` queue
β€’ Validates each operation and its encrypted inputs
β€’ Creates a placeholder record for every result handle
β€’ Routes validated FHE operations to the `engine-requests` queue | - -The FheOS Server sits between the chain and the execution layer. [Slim Listeners](/deep-dive/cofhe-components/slim-listener) publish TaskManager events into the `blockchain-events` queue. The FheOS Server consumes them, checks that each operation is well formed and its inputs exist, and enqueues the validated work for the FHE Engine. It does not execute FHE operations itself, and it exposes no API beyond a health endpoint. - -## Ordering and failure handling - -Operations can arrive before the inputs they depend on have finished computing. The FheOS Server defers such operations and releases them once the missing results land, so out-of-order delivery never produces a wrong answer. Messages that are malformed or reference inputs that never materialize are routed to a dead-letter queue instead of being silently dropped. - -## What it is not - -The FheOS Server is frequently mistaken for the execution engine. Execution happens in the [FHE Engine](/deep-dive/cofhe-components/fhe-engine), and decryption happens in [Teecryptor](/deep-dive/cofhe-components/teecryptor). The FheOS Server verifies and orchestrates. diff --git a/deep-dive/cofhe-components/slim-listener.mdx b/deep-dive/cofhe-components/slim-listener.mdx deleted file mode 100644 index c5ab62f..0000000 --- a/deep-dive/cofhe-components/slim-listener.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: Slim Listener -description: "Offchain service that watches TaskManager events on each host chain and relays them into the coprocessor's queues" ---- - -| Aspect | Description | -|--------|-------------| -| **Type** | Offchain event relay service. | -| **Function** | Watches TaskManager events on a host chain and publishes them to the coprocessor's queues. | -| **Responsibilities** | β€’ Monitors events emitted by the TaskManager contract on its host chain
β€’ Relays FHE operation events for execution
β€’ Relays verified-input events for commitment posting | - -The Slim Listener is the bridge between onchain events and the offchain services. One instance runs per host chain per flow, and each instance does one narrow job: - -| Flow | Watches | Publishes to | Purpose | -|------|---------|--------------|---------| -| FHE operations | `TaskCreated` | `blockchain-events` queue | Feeds the [FheOS Server](/deep-dive/cofhe-components/fheos-server) with work to validate and route. | -| Verified inputs | `InputVerified` | `commitment-requests` queue | Anchors a commitment for every verified input, so [Teecryptor](/deep-dive/cofhe-components/teecryptor) can later decrypt it. | - -Delivery is reliable by construction. The listener publishes with confirms and tracks the last processed block, so a crash or a missed range is re-scanned rather than skipped. diff --git a/docs.json b/docs.json index 62a2df4..1e50305 100644 --- a/docs.json +++ b/docs.json @@ -238,11 +238,9 @@ "deep-dive/cofhe-components/overview", "deep-dive/cofhe-components/task-manager", "deep-dive/cofhe-components/acl", - "deep-dive/cofhe-components/slim-listener", "deep-dive/cofhe-components/plaintext-storage", "deep-dive/cofhe-components/commitment-registry", "deep-dive/cofhe-components/zk-verifier", - "deep-dive/cofhe-components/fheos-server", "deep-dive/cofhe-components/fhe-engine", "deep-dive/cofhe-components/teecryptor", "deep-dive/cofhe-components/key-management" @@ -313,6 +311,14 @@ "source": "/deep-dive/cofhe-components/threshold-network", "destination": "/deep-dive/cofhe-components/teecryptor" }, + { + "source": "/deep-dive/cofhe-components/slim-listener", + "destination": "/deep-dive/cofhe-components/fhe-engine" + }, + { + "source": "/deep-dive/cofhe-components/fheos-server", + "destination": "/deep-dive/cofhe-components/fhe-engine" + }, { "source": "/deep-dive/cofhe-components/result-processor", "destination": "/deep-dive/cofhe-components/fhe-engine" From 04546cdfff1f32b603e919a4ef093991d70790fe Mon Sep 17 00:00:00 2001 From: haim Date: Thu, 27 Aug 2026 17:47:09 +0300 Subject: [PATCH 48/58] [DOCS] cofhe-components/overview: big-blocks architecture diagram, FHE Engine as one component --- deep-dive/cofhe-components/overview.mdx | 45 +++++++++++-------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index dd56daa..b58386b 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -8,21 +8,18 @@ CoFHE (Coprocessor for Fully Homomorphic Encryption) lets smart contracts comput ```mermaid %%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220, "actorFontSize": 16, "messageFontSize": 16, "noteFontSize": 15}}}%% flowchart TB - PRT["Partners (key custodians)"] - subgraph App["Application"] SDK["Client SDK"] end - subgraph CoFHE["CoFHE services (offchain)"] - subgraph TEES[" "] - TEE["Teecryptor (TEE)"] - ZK["ZK Verifier"] - end - CTS["CT Server"] - subgraph K8S[" "] - direction LR - SL["Slim Listener"] --> FheOS["FheOS Server"] --> Engine["FHE Engine"] -- "commitments" --> BP["Blockchain Poster"] + subgraph CoFHE["CoFHE (offchain)"] + TEE["Teecryptor (TEE)"] + ZK["ZK Verifier (TEE)"] + PRT["Partners (key custodians)"] + CTS[("Ciphertext store")] + subgraph ENG["FHE Engine"] + direction TB + L["subscribe to task events"] --> X["process FHE computation"] --> P["post commitments"] end end @@ -36,22 +33,23 @@ flowchart TB CR["CommitmentRegistry"] end + SDK -- "encrypt inputs" --> ZK SDK -- "decrypt" --> TEE + SDK -- "publish result" --> TM + FHEC --> TM + TM --> PS TEE -- "ACL check" --> TM TEE -- "fetch ciphertext" --> CTS TEE -- "verify commitment" --> CR - SDK -- "encrypt inputs" --> ZK ZK -- "store ciphertext" --> CTS - FHEC --> TM - TM -- "task events" --> K8S - K8S -- "post commitments" --> CR - SDK -- "publish result" --> TM - TM --> PS + ENG <-- "ciphertexts" --> CTS + TM -- "task events" --> ENG + ENG -- "post commitments" --> CR PRT -- "key shares (attested)" --> TEE PRT -- "signing key (attested)" --> ZK - linkStyle 7,8 stroke:#7FDB8F - linkStyle 3,4,5,6,12,13 stroke:#0AD9DC + linkStyle 2,10 stroke:#7FDB8F + linkStyle 3,4,7,8,9 stroke:#0AD9DC linkStyle 14,15 stroke:#E0C36A ``` @@ -67,16 +65,11 @@ flowchart TB - **[Client SDK](/client-sdk/introduction/overview)** (`@cofhe/sdk`): the TypeScript library applications use to encrypt inputs, manage [permits](/client-sdk/guides/permits), and decrypt outputs. - **[ZK Verifier](/deep-dive/cofhe-components/zk-verifier)**: a standalone service that verifies encrypted inputs in batches. It checks each zero-knowledge proof, stores the ciphertexts, and signs one approval for the whole batch. -- **[Slim Listener](/deep-dive/cofhe-components/slim-listener)**: watches TaskManager events on each host chain and forwards them into the coprocessor's queues. -- **[FheOS Server](/deep-dive/cofhe-components/fheos-server)**: ingests task events, verifies inputs, creates result placeholders, and routes work to the FHE Engine. It does not execute FHE operations itself. -- **[FHE Engine](/deep-dive/cofhe-components/fhe-engine)**: executes every FHE operation on encrypted data, persists the resulting ciphertexts, and emits a commitment for each result. -- **CT Server**: the gate to the ciphertext database. Every ciphertext read and write for the other services goes through it. -- **Blockchain Poster**: batches result commitments and posts them to the CommitmentRegistry. +- **[FHE Engine](/deep-dive/cofhe-components/fhe-engine)**: the execution pipeline. It subscribes to TaskManager events, validates and orders operations, runs them on encrypted data, and posts a commitment for every result. +- **Ciphertext store**: the database that holds every ciphertext, fronted by the CT Server. The ZK Verifier writes verified inputs, the FHE Engine reads operands and writes results, and Teecryptor fetches bytes to decrypt. - **[Teecryptor](/deep-dive/cofhe-components/teecryptor)**: the decryption service. It runs inside a hardware-attested TEE, authorizes every request against the onchain ACL, verifies the ciphertext commitment, and returns signed or sealed results. - **Partners**: independent custodians of the key material. Each holds a Shamir share and releases it only to an attested enclave. See [Key Management](/deep-dive/cofhe-components/key-management). -Services communicate through message queues rather than direct calls, so each stage can retry and scale independently. - ## Data flows 1. **[Encryption request](/deep-dive/data-flows/encryption-request-flow)**: an input is encrypted client-side and proven valid with a zero-knowledge proof before it enters the chain. From 3ec0ddd9524838410e2073df905a4233fe250284 Mon Sep 17 00:00:00 2001 From: haim Date: Thu, 27 Aug 2026 17:47:09 +0300 Subject: [PATCH 49/58] [DOCS] data-flows/fhe-operation-request-flow: engine pipeline stages replace per-service steps and queues --- .../data-flows/fhe-operation-request-flow.mdx | 31 ++++++------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/deep-dive/data-flows/fhe-operation-request-flow.mdx b/deep-dive/data-flows/fhe-operation-request-flow.mdx index e9d4004..bde5255 100644 --- a/deep-dive/data-flows/fhe-operation-request-flow.mdx +++ b/deep-dive/data-flows/fhe-operation-request-flow.mdx @@ -13,10 +13,7 @@ This page follows a single FHE operation from the contract call that requests it | **Your contract** | Requests FHE operations through the FHE.sol library | | **FHE.sol** | The Solidity library providing FHE operation functions | | **[TaskManager](/deep-dive/cofhe-components/task-manager)** | Validates requests, checks the [ACL](/deep-dive/cofhe-components/acl), and emits task events | -| **[Slim Listener](/deep-dive/cofhe-components/slim-listener)** | Watches TaskManager events on each host chain and enqueues them | -| **[FheOS Server](/deep-dive/cofhe-components/fheos-server)** | Ingests task events, validates them, and routes work to the FHE Engine | -| **[FHE Engine](/deep-dive/cofhe-components/fhe-engine)** | Executes the FHE operation and stores the result ciphertext | -| **Blockchain Poster** | Batches result commitments and posts them onchain | +| **[FHE Engine](/deep-dive/cofhe-components/fhe-engine)** | Picks up task events, validates and orders the work, executes it, and commits the result | | **[CommitmentRegistry](/deep-dive/cofhe-components/commitment-registry)** | Records a hash commitment for every result ciphertext | ## Flow diagram @@ -26,21 +23,16 @@ This page follows a single FHE operation from the contract call that requests it sequenceDiagram participant Contract as Your contract (FHE.sol) participant TM as TaskManager - participant SL as Slim Listener - participant FheOS as FheOS Server participant Engine as FHE Engine - participant BP as Blockchain Poster participant CR as CommitmentRegistry Contract->>TM: FHE.add(lhs, rhs) calls createTask TM->>TM: validate inputs, check ACL TM-->>Contract: result handle (synchronous) - TM->>SL: TaskCreated event - SL->>FheOS: blockchain-events queue - FheOS->>Engine: engine-requests queue + TM->>Engine: TaskCreated event + Engine->>Engine: validate and order the task Engine->>Engine: execute op, store ciphertext under the handle - Engine->>BP: commitment-requests queue - BP->>CR: postCommitments (batched) + Engine->>CR: postCommitments (batched) ``` ## Step-by-step flow @@ -87,25 +79,20 @@ The TaskManager is the gateway for all FHE operation requests. It: 5. Emits a `TaskCreated` event with the operation details for the offchain services. - -One Slim Listener instance runs per host chain per flow. This flow's listener watches for `TaskCreated` events and publishes them to the coprocessor's `blockchain-events` queue. + +The [FHE Engine](/deep-dive/cofhe-components/fhe-engine) subscribes to TaskManager events on every host chain and picks up the `TaskCreated` event. It checks that the operation is well formed and that the inputs it references exist. An operation that arrives before its inputs finish computing is deferred and released once they land. - -The FheOS Server consumes `blockchain-events`, validates the task, and routes FHE operations to the `engine-requests` queue. It does not execute operations itself. - - - -The FHE Engine consumes `engine-requests` and: + +The engine then: 1. Executes the requested operation on the encrypted data. 2. Stores the result ciphertext in the ciphertext database, keyed by the handle. 3. Releases any dependent operations that were deferred while waiting for this result. -4. Publishes a commitment for the result (the hash of the stored ciphertext bytes) to the `commitment-requests` queue. -The Blockchain Poster batches commitments and posts them to the CommitmentRegistry on the registry chain. The commitment anchors the result. Teecryptor will only decrypt ciphertext bytes that hash to a registered commitment. +The engine produces a commitment for the result, the hash of the stored ciphertext bytes, and posts it in a batch to the CommitmentRegistry on the registry chain. The commitment anchors the result. Teecryptor will only decrypt ciphertext bytes that hash to a registered commitment. At this point the operation cycle is complete, and the confidentiality of every encrypted value is preserved. From a98a8a696269f1f93d775c5afaebe90e7d5f9b05 Mon Sep 17 00:00:00 2001 From: haim Date: Thu, 27 Aug 2026 17:47:09 +0300 Subject: [PATCH 50/58] [DOCS] cofhe-components/commitment-registry: poster is an engine stage, not a named service --- deep-dive/cofhe-components/commitment-registry.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deep-dive/cofhe-components/commitment-registry.mdx b/deep-dive/cofhe-components/commitment-registry.mdx index 045be8f..1dce5e0 100644 --- a/deep-dive/cofhe-components/commitment-registry.mdx +++ b/deep-dive/cofhe-components/commitment-registry.mdx @@ -12,7 +12,7 @@ description: "Registry-chain contract that records FHE computation commitments. ## What a commitment is -A commitment is the `keccak256` hash of a ciphertext's canonical stored bytes. The [FHE Engine](/deep-dive/cofhe-components/fhe-engine) produces one for every result it computes, and the coprocessor anchors one for every encrypted input it verifies. The Blockchain Poster batches them and writes them to this registry. +A commitment is the `keccak256` hash of a ciphertext's canonical stored bytes. The [FHE Engine](/deep-dive/cofhe-components/fhe-engine) produces one for every result it computes, and the coprocessor anchors one for every encrypted input it verifies. The engine batches them and writes them to this registry. ## Why commitments? @@ -56,7 +56,7 @@ The admin-only `setVersionStatus(version, newStatus)` enforces these transitions ## Write surface -Only accounts holding the **poster** role can write commitments (`postCommitments`, `postCommitmentsSafe`); posts from anyone else revert with `OnlyPosterAllowed(caller)`. Poster management and version transitions are admin-only. In production, the poster role is held by the Blockchain Poster service's relayer signer (OpenZeppelin Relayer). +Only accounts holding the **poster** role can write commitments (`postCommitments`, `postCommitmentsSafe`); posts from anyone else revert with `OnlyPosterAllowed(caller)`. Poster management and version transitions are admin-only. In production, the poster role is held by the coprocessor's relayer signer (OpenZeppelin Relayer). ## Writing commitments From ee4d1866e62f324c7c6e765985d86fb453089b5c Mon Sep 17 00:00:00 2001 From: haim Date: Thu, 27 Aug 2026 17:47:09 +0300 Subject: [PATCH 51/58] [DOCS] introduction/what-is-cofhe: current component table, drop retired result processor and threshold network rows --- get-started/introduction/what-is-cofhe.mdx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/get-started/introduction/what-is-cofhe.mdx b/get-started/introduction/what-is-cofhe.mdx index f5ccadb..6c016c7 100644 --- a/get-started/introduction/what-is-cofhe.mdx +++ b/get-started/introduction/what-is-cofhe.mdx @@ -89,11 +89,8 @@ Developers only interact directly with **two** parts of CoFHE; the rest runs beh | Component | Role | | --- | --- | | **Task Manager** | Onchain gateway that validates FHE requests and enforces access control | -| **Slim Listener** | Watches onchain events and forwards operations to the offchain layer | -| **FheOS Server** | Verifies incoming work and queues it. It does not execute FHE operations | -| **FHE Engine** | Executes the FHE operations on encrypted data | -| **Result Processor** | Publishes verified results back onchain | -| **Threshold Network** | Decrypts via multi-party computation, no single party holds the key | +| **FHE Engine** | Picks up onchain task events, validates and orders them, executes the FHE operations on encrypted data, and commits results | +| **Teecryptor** | Decrypts inside a hardware-attested TEE, after checking permissions and commitments | | **Registries** | Track ciphertexts and record result commitments so integrity can be verified before any decryption | For a component-by-component breakdown, see the [CoFHE Architecture deep dive](/deep-dive/cofhe-components/overview). From e2339ab5393541d37c31903d94c2544c7d5d188c Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 30 Aug 2026 14:45:02 +0300 Subject: [PATCH 52/58] [DOCS] cofhe-components/overview: your contract sits outside CoFHE, both TEEs move to MPC --- deep-dive/cofhe-components/overview.mdx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index b58386b..45ecb02 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -8,6 +8,10 @@ CoFHE (Coprocessor for Fully Homomorphic Encryption) lets smart contracts comput ```mermaid %%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220, "actorFontSize": 16, "messageFontSize": 16, "noteFontSize": 15}}}%% flowchart TB + subgraph Yours["Your code (outside CoFHE)"] + FHEC["Your contract, uses FHE.sol"] + end + subgraph App["Application"] SDK["Client SDK"] end @@ -24,7 +28,6 @@ flowchart TB end subgraph Host["Host chain"] - FHEC["Your contract + FHE.sol"] TM["TaskManager + ACL"] PS["PlaintextsStorage"] end @@ -51,6 +54,9 @@ flowchart TB linkStyle 2,10 stroke:#7FDB8F linkStyle 3,4,7,8,9 stroke:#0AD9DC linkStyle 14,15 stroke:#E0C36A + + style Yours stroke-dasharray: 6 4 + style PRT stroke-dasharray: 6 4 ``` ## The onchain contracts @@ -78,4 +84,4 @@ flowchart TB ## Future plans -Decryption is currently performed by Teecryptor inside a hardware-attested TEE. A multi-party [Threshold Network](/deep-dive/research/future-plans) is the planned successor. +Two components run inside hardware-attested TEEs today: Teecryptor, which decrypts, and the ZK Verifier, which checks input proofs. Both move to multi-party computation in one planned step. See [Future Plans](/deep-dive/research/future-plans). From a946e9a192209d38fc0187044d9f940e439e9af8 Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 30 Aug 2026 14:45:02 +0300 Subject: [PATCH 53/58] [DOCS] research/future-plans: ZK Verifier moves to MPC together with Teecryptor --- deep-dive/research/future-plans.mdx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/deep-dive/research/future-plans.mdx b/deep-dive/research/future-plans.mdx index 90367e8..af3cf4a 100644 --- a/deep-dive/research/future-plans.mdx +++ b/deep-dive/research/future-plans.mdx @@ -12,19 +12,24 @@ Outlined here is a non-exhaustive list of trust points, centralized components, | Component | Compromise | Plan to solve | Status | | --- | --- | --- | --- | -| Teecryptor | Decryption is served by a single TEE service operated by Fhenix | Replace with the Threshold Network (below) | Planned | -| Teecryptor | Trust in the TEE hardware vendor and its attestation chain | Threshold decryption removes the hardware trust anchor | Planned | +| Teecryptor | Decryption is served by a single TEE service operated by Fhenix | Replace with multi-party computation (below) | Planned | +| Teecryptor | Trust in the TEE hardware vendor and its attestation chain | Multi-party computation removes the hardware trust anchor | Planned | +| ZK Verifier | Input proofs are checked by a single TEE service operated by Fhenix | Move to multi-party computation, with each partner verifying inputs on its own side | Planned | | Key custody | The FHE key is reconstructed inside one attested enclave at runtime | Threshold decryption, where no party ever holds the full key | Planned | | CoFHE | Trust in CoFHE to perform correct FHE computations | External verification | Planned | | CoFHE | User inputs stored in a centralized manner | Use a decentralized DA | Planned | | All | Codebase is unaudited | Perform a security audit | Planned | | All | Codebase is not fully open source | Open-source the codebase | Planned | -One earlier training wheel has already been removed: the ZK Verifier now runs inside a hardware-attested TEE, with its signing key released only to the attested code image. +One training wheel has already been narrowed: the ZK Verifier now runs inside a hardware-attested TEE, with its signing key released only to the attested code image. The enclave itself stays a trust point until the move described below. -## The path to the Threshold Network +## The path to multi-party computation -The end state for decryption is a Threshold Network. Independent parties decrypt through multi-party computation, so no single party (and no single machine) ever holds the FHE key. It will replace [Teecryptor](/deep-dive/cofhe-components/teecryptor) and remove the trust points listed above in one move. Robustness goals for it include a t-out-of-n protocol (no requirement that every party stays online), party share rotation, and full protocol key rotation. +CoFHE runs two TEE services today, [Teecryptor](/deep-dive/cofhe-components/teecryptor) and the [ZK Verifier](/deep-dive/cofhe-components/zk-verifier). Both move to multi-party computation, and they move together. No TEE stays on the critical path after that. + +Decryption becomes a Threshold Network. Independent parties decrypt through multi-party computation, so no single party (and no single machine) ever holds the FHE key. Robustness goals for it include a t-out-of-n protocol (no requirement that every party stays online), party share rotation, and full protocol key rotation. + +Input verification follows the same model. Each partner runs ZK verification on its own side, instead of one attested enclave checking every proof and signing the batch alone. See [Research in Fhenix](/deep-dive/research/research-in-fhenix) for the threshold decryption protocol behind this plan. From 420def9821f1cf7a7d069644db63ee9c5aff5aac Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 30 Aug 2026 14:45:18 +0300 Subject: [PATCH 54/58] [DOCS] introduction/what-is-cofhe: stamp the shared mermaid theme on the sequence diagram --- get-started/introduction/what-is-cofhe.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/get-started/introduction/what-is-cofhe.mdx b/get-started/introduction/what-is-cofhe.mdx index 6c016c7..7decd9d 100644 --- a/get-started/introduction/what-is-cofhe.mdx +++ b/get-started/introduction/what-is-cofhe.mdx @@ -48,6 +48,7 @@ When an authorized user wants a result, they present a signed [Access Control Pe
```mermaid +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220, "actorFontSize": 16, "messageFontSize": 16, "noteFontSize": 15}}}%% sequenceDiagram participant User participant SDK as "@cofhe/sdk" From 86e48312f9b2ba3c99dcac787b90a15778f2463c Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 30 Aug 2026 14:45:18 +0300 Subject: [PATCH 55/58] [DOCS] cofhe-components/fhe-engine: resync mermaid init with the shared theme --- deep-dive/cofhe-components/fhe-engine.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deep-dive/cofhe-components/fhe-engine.mdx b/deep-dive/cofhe-components/fhe-engine.mdx index 66660cf..83162db 100644 --- a/deep-dive/cofhe-components/fhe-engine.mdx +++ b/deep-dive/cofhe-components/fhe-engine.mdx @@ -12,7 +12,7 @@ description: "The offchain execution pipeline that carries a task from onchain e The FHE Engine is the computation side of CoFHE. Contracts never call it; it subscribes to what happens onchain, does the encrypted math, and anchors the results. From the outside it is one component with four stages. ```mermaid -%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}}}%% +%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220, "actorFontSize": 16, "messageFontSize": 16, "noteFontSize": 15}}}%% flowchart LR TM["TaskManager events"] --> L["Listen"] --> V["Validate and order"] --> X["Execute"] --> C["Commit"] --> CR["CommitmentRegistry"] ``` From ef5f77808faffd70b137258374054e09ac04b2db Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 30 Aug 2026 15:15:41 +0300 Subject: [PATCH 56/58] [DOCS] cofhe-components/overview: diagram matches the reviewed structure, TEE enclaves and node subtitles --- deep-dive/cofhe-components/overview.mdx | 34 ++++++++++++++----------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index 45ecb02..d589462 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -9,31 +9,35 @@ CoFHE (Coprocessor for Fully Homomorphic Encryption) lets smart contracts comput %%{init: {"theme": "base", "themeVariables": {"fontFamily": "Menlo, Monaco, Consolas, monospace", "fontSize": "16px", "primaryColor": "#8FBAF5", "primaryBorderColor": "#2E7CF6", "primaryTextColor": "#0A1626", "lineColor": "#4C8DFF", "signalColor": "#4C8DFF", "signalTextColor": "#8FA3BF", "actorBkg": "#8FBAF5", "actorBorder": "#2E7CF6", "actorTextColor": "#0A1626", "actorLineColor": "#3D4654", "noteBkgColor": "#14171C", "noteBorderColor": "#3D4654", "noteTextColor": "#AFC3DE", "activationBkgColor": "#1E3A5F", "activationBorderColor": "#4C8DFF", "clusterBkg": "#14171C", "clusterBorder": "#3D4654", "titleColor": "#E7EAEE", "edgeLabelBackground": "#8FBAF5", "textColor": "#AFC3DE", "labelTextColor": "#E7EAEE", "tertiaryColor": "#14171C", "loopTextColor": "#AFC3DE", "labelBoxBkgColor": "#1E3A5F", "labelBoxBorderColor": "#4C8DFF"}, "sequence": {"actorFontFamily": "Menlo, Monaco, Consolas, monospace", "messageFontFamily": "Menlo, Monaco, Consolas, monospace", "noteFontFamily": "Menlo, Monaco, Consolas, monospace", "width": 220, "actorFontSize": 16, "messageFontSize": 16, "noteFontSize": 15}}}%% flowchart TB subgraph Yours["Your code (outside CoFHE)"] - FHEC["Your contract, uses FHE.sol"] + FHEC["Your contract
uses FHE.sol"] end subgraph App["Application"] - SDK["Client SDK"] + SDK["Client SDK
client-side library"] end - subgraph CoFHE["CoFHE (offchain)"] - TEE["Teecryptor (TEE)"] - ZK["ZK Verifier (TEE)"] - PRT["Partners (key custodians)"] + subgraph Host["Host chain"] + TM["TaskManager + ACL
tasks, permissions"] + PS["PlaintextsStorage
decrypted results"] + end + + subgraph CoFHE["CoFHE"] + subgraph TEEBOX["TEE enclave"] + TEE["Teecryptor
key shares"] + end + subgraph ZKBOX["TEE enclave"] + ZK["ZK Verifier
signing key"] + end + PRT["Partners
key custodians"] CTS[("Ciphertext store")] subgraph ENG["FHE Engine"] direction TB - L["subscribe to task events"] --> X["process FHE computation"] --> P["post commitments"] + L["subscribe to task events"] --> X["process FHE computation"] --> P["post commitments to registry"] end end - subgraph Host["Host chain"] - TM["TaskManager + ACL"] - PS["PlaintextsStorage"] - end - subgraph Registry["Registry chain"] - CR["CommitmentRegistry"] + CR["CommitmentRegistry
op commitments"] end SDK -- "encrypt inputs" --> ZK @@ -46,8 +50,8 @@ flowchart TB TEE -- "verify commitment" --> CR ZK -- "store ciphertext" --> CTS ENG <-- "ciphertexts" --> CTS - TM -- "task events" --> ENG - ENG -- "post commitments" --> CR + TM --> L + P --> CR PRT -- "key shares (attested)" --> TEE PRT -- "signing key (attested)" --> ZK From 1479eeb2dee666c6da852576da094e18049b75da Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 30 Aug 2026 15:15:41 +0300 Subject: [PATCH 57/58] [DOCS] style: FHE Engine is one name, drop the retired FheOS Server entry --- STYLE.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/STYLE.md b/STYLE.md index 1a82c62..de7bc96 100644 --- a/STYLE.md +++ b/STYLE.md @@ -63,8 +63,7 @@ One name per thing, used consistently. Canonical names: |---|---| | CoFHE | The coprocessor as a whole. Not COFHE, not Cofhe. | | Teecryptor | The TEE decryption service. Capitalized as a product name. | -| FHE Engine | The service that executes FHE operations. | -| FheOS Server | The service that verifies and queues incoming work. It does not execute FHE operations. | +| FHE Engine | The offchain pipeline that subscribes to task events, executes FHE operations, and posts commitments. One name for the whole pipeline; its internal stages are not named in public docs. | | ZK Verifier | The input proof verification service. | | TaskManager, CommitmentRegistry, ACL | Contract names, written as in the source. | | ACP | Access Control Permission. Replaces "Permit" from `0.7` onward, so that it is not confused with an ERC-2612 permit. Spell it out before the acronym: a page whose subject is ACPs carries the full term in its `title`, and every other page expands it on first use. Never write "ACP permission". | From 348e4753b7ee87ec4f587260fa29729a0eae57ec Mon Sep 17 00:00:00 2001 From: haim Date: Sun, 30 Aug 2026 15:31:21 +0300 Subject: [PATCH 58/58] [DOCS] cofhe-components/overview: simplify the diagram, drop the color overlay and redundant edge labels --- deep-dive/cofhe-components/overview.mdx | 28 +++++++++---------------- 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/deep-dive/cofhe-components/overview.mdx b/deep-dive/cofhe-components/overview.mdx index d589462..4988e23 100644 --- a/deep-dive/cofhe-components/overview.mdx +++ b/deep-dive/cofhe-components/overview.mdx @@ -22,12 +22,8 @@ flowchart TB end subgraph CoFHE["CoFHE"] - subgraph TEEBOX["TEE enclave"] - TEE["Teecryptor
key shares"] - end - subgraph ZKBOX["TEE enclave"] - ZK["ZK Verifier
signing key"] - end + TEE["Teecryptor
TEE enclave, key shares"] + ZK["ZK Verifier
TEE enclave, signing key"] PRT["Partners
key custodians"] CTS[("Ciphertext store")] subgraph ENG["FHE Engine"] @@ -40,24 +36,20 @@ flowchart TB CR["CommitmentRegistry
op commitments"] end - SDK -- "encrypt inputs" --> ZK + FHEC --> TM + SDK -- "encrypt" --> ZK SDK -- "decrypt" --> TEE SDK -- "publish result" --> TM - FHEC --> TM TM --> PS + TM --> L TEE -- "ACL check" --> TM - TEE -- "fetch ciphertext" --> CTS + TEE --> CTS TEE -- "verify commitment" --> CR - ZK -- "store ciphertext" --> CTS - ENG <-- "ciphertexts" --> CTS - TM --> L + ZK --> CTS + ENG <--> CTS P --> CR - PRT -- "key shares (attested)" --> TEE - PRT -- "signing key (attested)" --> ZK - - linkStyle 2,10 stroke:#7FDB8F - linkStyle 3,4,7,8,9 stroke:#0AD9DC - linkStyle 14,15 stroke:#E0C36A + PRT --> TEE + PRT --> ZK style Yours stroke-dasharray: 6 4 style PRT stroke-dasharray: 6 4