
Blog · Turnstile series, part 8
Sell the answer, keep the method: Chainlink CRE Confidential Workflows
What a confidential workflow is, how Chainlink runs one, how it lets a paid agent sell a verdict without publishing its edge, and where it stops.
TL;DR
Turnstile sells one answer per payment: is this Uniswap pool safe to provide liquidity to? A good answer has an awkward property. Publish how you got it and nobody needs to pay you. Hide it and nobody can trust it.
Confidential compute is the way out: run the method where nobody can look, and prove that it ran. Chainlink's version is the Confidential Workflow, part of the Chainlink Runtime Environment (CRE).
- What it is. A CRE workflow that runs part of its logic inside a secure enclave, a hardware-isolated environment that even the machine's operator cannot look into.
- What it hides. Data, not code. Secrets, inputs and intermediate values stay inside; the workflow's code is public. So if your edge is worth hiding, it has to be data.
- How we used it. The scorer's logic is public. Its tuned thresholds go in as a secret. Only a short verdict and a hash of the evidence come out.
The code is at github.com/IpastorSan/turnstile.
Part 8 of 9 in the Turnstile series: building a paid lane for onchain data agents.
The problem: selling an answer whose method is the edge
The rest of this series is about how an agent pays for data: x402 on Hedera, gasless nanopayments on Arc, a seller that takes any rail, and discovery through ERC-8004 and ENS. The product being sold is a liquidity analyst that reads a pool's history and live depth and answers one question: is it safe to LP?
Under the payments sits an economic problem. If the analyst is good, publishing its method gives away the reason to pay. If you keep it private, the buyer has to take a stranger's word on faith. A verdict you can't check isn't worth much, and one you can fully reproduce isn't worth buying.
We needed something in between: a verdict the buyer can check, from a method they can't copy.
What confidential compute is
A trusted execution environment (TEE) is a part of a processor that runs code in isolation. Its memory is encrypted, and neither the operating system nor the person who owns the machine can read it while the code runs. A running instance is called an enclave. AWS Nitro Enclaves is one example, and it is the one Chainlink uses today.
A TEE gives you two things.
- Confidentiality. What happens inside can't be read from outside while it runs.
- Attestation. The hardware signs a statement saying which program is running. Anyone can check that signature and know which program produced an output, and that nobody tampered with it along the way.
It does not give you everything. The output is only as private as you make it: whatever the code logs, returns or sends leaves the enclave. You also trust the hardware vendor, and side-channel attacks have broken enclaves before.
A TEE on its own also leaves one job to the buyer: checking the attestation. A seller could run the scorer in an enclave and publish the signed statement, but then every buyer has to verify it themselves and trust that the seller published the right one. That is the job Chainlink takes on.
How Chainlink's Confidential Workflows work
The Chainlink Runtime Environment (CRE) is Chainlink's platform for running your own code on its oracle networks, instead of only reading the data they publish. The unit of code is a workflow: a program, written in Go or TypeScript and compiled to WebAssembly, that runs when a trigger fires, such as a schedule, an HTTP request or an onchain event. A Workflow DON (decentralized oracle network, a set of independent nodes) runs it. Each node executes the step and the nodes reach consensus on the result. That is good for trust and bad for secrets, because every node operator can, in principle, see what is being computed.
A Confidential Workflow marks one handler to run inside an enclave instead. Per Chainlink's docs, it goes like this:
- The trigger fires, and the Workflow DON hands the request to an enclave.
- The handler runs inside the enclave.
- Secrets are fetched when the code needs them. They come from the Vault DON, Chainlink's network for storing secrets, and are decrypted only inside the enclave.
- The code crosses back to the DON when it needs something only the DON can do, such as signing a report to put on chain. From that point on, whatever crosses is ordinary data, not confidential.
- The DON verifies the enclave's attestation by consensus. The workflow only completes once that check passes.
- A Forwarder contract delivers the signed report to your consumer contract on chain.
flowchart TB
D1["Workflow DON<br/>a trigger fires"] -->|"hands the request over"| ENC["Enclave<br/>runs the confidential handler"]
V["Vault DON"] -.->|"secrets, decrypted only inside"| ENC
ENC -->|"only what you choose to send out"| D2["Workflow DON<br/>checks the attestation, signs the report"]
D2 --> F["Forwarder contract"]
F --> C["Your consumer contract"]
The consumer contract is where the trust becomes checkable on chain. It accepts reports only from the Forwarder, and it can also require a specific workflow id and owner. A buyer doesn't verify enclave signatures. They read a contract that only a verified workflow can write to.
The docs are precise about what this protects:
| Protected | Not protected |
|---|---|
| Secrets the Vault DON releases into the enclave | The workflow's source code and compiled binary |
| Inputs and intermediate values you keep inside | Triggers, chain reads and chain writes, which always run on the DON |
| The enclave's memory while it runs | Reports, logs and anything else you send out |
The first row of the right-hand column is the one that shaped our design. In Chainlink's words: "Your handler's source code and compiled binary are not confidential just because part of its logic runs inside an enclave."
Compared with a classic oracle, the thing being agreed on is different. An oracle network agrees on a public fact, like a price, that every node can check. Here nobody but the enclave sees the inputs, so the network cannot agree on the answer. What it agrees on is that a verified enclave ran this program.
How it fits Turnstile
If the code is public, a secret threshold written into the code is public too. So we sorted each piece by whether it has to stay secret.
| Part | What it is | How it moves | Secret? |
|---|---|---|---|
| Calibration | the tuned thresholds | into the enclave, as a Vault DON secret | yes |
| Evidence | the pool's history and live depth | into the enclave, fetched with a token held in the Vault | yes |
| Scorer | which signals exist and how they combine | compiled into the workflow | no, on purpose |
| Verdict | rating, confidence, which tests failed or warned, a hash of the evidence | out of the enclave, to the DON and then on chain | no |
The shape of the judgement should be public: which seven signals the scorer checks, and which ones force an AVOID verdict on their own. That is what makes a result auditable instead of an oracle you take on faith.
The calibration is different. It is what running the scorer against real pools taught us. Take trading continuity, one of the seven signals: it counts how many of the last 24 hours saw a trade. Below half, the pool gets a warning for trading in bursts. At or below a lower cutoff, it fails outright, because that is not a market. We first set that cutoff at 10% of hours. Then a real TRUMP/WETH pool traded in 3 hours out of 24, $1.54 of volume in total, and at 10% it only got the warning. We raised the cutoff to 20%, and that pool now fails as it should. That tuning is the analyst's edge, so it lives in the Vault. The numbers in our public repo are a reference set; a seller's own set is the secret.
What goes on chain is deliberately small. The full verdict, with a reasoning paragraph and numbers for each signal, is what the buyer pays for over x402, off chain. The chain holds only the rating, the confidence, which tests failed or warned, the time the evidence describes, and a hash of the evidence. The hash is what ties the two together. A buyer who paid has the evidence, hashes it and asks the contract whether the settled verdict commits to that exact hash. If it does, the verdict is about the data they hold. If not, the seller swapped the evidence, and the buyer can prove it. Someone who hasn't paid learns nothing from a hash.
Trust is not a boolean
A verdict being on chain doesn't by itself mean an enclave produced it. That depends on who delivered it and on what the consumer contract checks. So the premium answer doesn't carry a verified: true flag. It tells the buyer which of four cases they are in:
- None. No verdict for this pool is on chain. The buyer has only the seller's word.
- Self-delivered. The contract accepts reports from an address other than Chainlink's Forwarder, so someone wrote this verdict directly. Our one verdict on Sepolia is this kind: we sent it ourselves to test the contract. It shows that the format and the evidence hash work, and proves nothing about an enclave.
- Forwarded, not pinned. It came through the Forwarder, so a Chainlink DON signed it, but the contract doesn't name the workflow it trusts. Any CRE workflow could have written it. Pinning needs the workflow's id, which only exists once the workflow is deployed.
- Attested. Through the Forwarder, from the one workflow the contract names. This is the only case that means our scorer ran inside an enclave.
Limitations
- Access. Confidential Workflows is a private beta that needs enrollment through Chainlink. Deploying any CRE workflow also needs approval, separately.
- The code isn't confidential. Keeping the logic itself secret is listed as a future feature. Today, if your edge is in the code, a confidential workflow doesn't hide it.
- Shared enclaves. Several confidential workflows can run in the same enclave, kept apart by the WebAssembly runtime. One enclave per workflow is planned.
- The usual TEE trust. You trust the hardware, and the docs warn that side-channel attacks may leak information.
- Leaks are on you. Logs, outputs and outgoing requests leave the enclave. Even our verdict says which tests failed, which hints at what the scorer cares about.
Sources
- Chainlink CRE overview: workflows in Go or TypeScript, run by a decentralized oracle network that reaches consensus on every result.
- CRE Confidential Workflows concept: the six steps, what is and isn't protected, code not confidential, shared enclaves, side channels, private beta.
- Requesting Confidential Workflows access: private beta, separate from deploy access, simulator usable meanwhile.
- Using secrets: local secrets in simulation, the Vault DON when deployed.
- Simulating workflows: chain writes are a dry run by default.
- Deploying workflows: deployment requires approval.
- Forwarder directory (TS): the Sepolia Forwarder our production contract is pinned to.
- smartcontractkit/cre-sdk-typescript: the TypeScript SDK and
cre.handlerInTee. - x402 docs: the HTTP 402 payment standard Turnstile sells over.
- Production consumer on Sepolia: pinned to the CRE Forwarder, no reports received.
- Stand-in settlement on Sepolia: the one verdict we delivered ourselves.
- Turnstile repository: the workflow in
seller/cre/, the consumer incontracts/src/VerdictConsumer.sol, and the simulator transcripts indocs/cre-confidential-workflow.md.
Next in the series: Selling a liquidity verdict: The Graph, Uniswap QuoterV2, and the gap between TVL and depth, part 9 of 9.


