zkDeal engineering · Technology Brief
More than a transaction, less than a chain
Trace an accepted zkDeal room checkpoint from the running system record to its Blockscout receipt and human-readable L1 transaction page.
CORE MODEL
zkdeal: more than a transaction, less than a chain
A guide to zkdeal's room model, capital path and relationship to the proving stacks used by ZK-based Ethereum L2s
Thesis: Most L2s prove a continuing shared chain. zkdeal proves one bounded room. An application chooses an allowed room profile; zkdeal binds that profile at room opening and proves each accepted checkpoint against it. The difference is lifecycle and settlement design, not a new cryptographic primitive.
Explore the architecture
Room anatomy: the app chooses; zkDeal pins and proves
Drag the canvas to pan, use the wheel or pinch gesture to zoom, and use the controls to zoom or fit the whole model. Expand for a page-sized view; press Escape to close it.
View the static reference image

Read the figure transcript
Room anatomy. The application chooses an allowed authorization mode, data route, lifecycle, proof template, participants, assets, clocks and application policy. zkdeal binds those choices when the room opens and verifies each accepted checkpoint against them. On the L1-funded validity path, consumed deposits credit their named beneficiaries before application execution and every room binds an exit route. The timing hierarchy is signed intent, room block, batch, accepted L1 checkpoint and Ethereum finality.
The five-stage time ladder and core vocabulary
Room: A room is an isolated EVM workflow with its own policy, assets, membership state and proof program. It has a deliberate close instead of running as one shared, always-on chain.
Settlement sequence: A signed intent enters a room block, and room blocks form a batch. The proof and journal turn that batch into an accepted L1 checkpoint. Ethereum finality makes the checkpoint canonical; until then, the room result remains provisional.
| Term | Plain meaning | Term | Plain meaning |
|---|---|---|---|
| Intent | A participant-authorized room transaction or application commitment. | Room block | A local EVM block; it is not an Ethereum block. |
| Batch | A proved sequence of room blocks; current hosted progress uses 2–4 room blocks. | Checkpoint | A proof-backed journal accepted by the L1 RoomManager. |
| Journal | A compact commitment to roots, data, cursors, liabilities, withdrawal leaves and close—not a readable event log. | Proof program | The RISC Zero guest/STF that re-executes the batch under the pinned policy. |
| Forced inbox | An L1 request that must be included, revert, receive a proved rejection, or halt room progress after its deadline. | RoomVault | L1 escrow with balances and liabilities segregated per room and asset. |
| Exit binding | A required validity-only policy component that pins how proved state becomes withdrawal leaves. | Terminal batch | A recovery-only final proof on deployment rails that support recovery close; the Stage-oriented validity rail exits through ordinary proof-bearing batches. |
Authorization, membership and checkpoint rhythm
Joint-consent rail: An application may choose unanimous approvers for a small jointly controlled room. Every active approver signs the same checkpoint journal, and participants keep the replay data. This is a deliberate consent-room option rather than the standard rollup Stage path.
Stage-oriented validity rail: An application may choose validity-only settlement with Ethereum calldata. Customers sign room transactions; the bound proof checks input and execution, while exact genesis data, deposits and forced inputs remain reconstructable from L1. The rollup-oriented deployment enforces this combination for every room it admits.
One-shot, rolling and sparse: A one-shot room closes at its first checkpoint; a rolling room checkpoints repeatedly; a sparse room waits longer. Sparse timing can amortize per-checkpoint submission overhead, but it also extends the rollback and operator-dependency window.
What the proof establishes—and what it does not
| Enforced after the validity rail is selected | Chosen by the application or deployment |
|---|---|
| Validity-proof authorization, exact-genesis binding, deterministic execution, state continuity, Ethereum-data binding and liability conservation. L1-funded validity rooms also enforce beneficiary credit and a room-bound route from proved state to L1 claims. | The application selects admission clocks, ordering and clearing, visibility, participant capacity, assets, confirmations and exit allocation from the deployment's allowed templates. Governance and the outer settlement profile belong to the deployment. |
Where the architecture is useful
Best fit: Choose a room when a high-value workflow has a clear beginning and end—for example, a deal, auction, game, fund episode or controlled settlement—and needs its own provable market rule and room-scoped L1 accounting.
Complementary fit: A persistent L2 remains the natural home for always-on composability, shared liquidity and broad wallet, RPC and indexer support. zkdeal can handle a bounded episode that begins in, returns to or coordinates with that wider market.
Use a continuing chain when: the application needs unrestricted contracts, permissionless entry, live cross-application composability or sustained chain-wide throughput during the episode. The eight-room recursive limit applies to one aggregate receipt; it is not a concurrency limit.
Motivational example
A proof claim should end at a transaction you can inspect
“The checkpoint was proved” is a useful internal log line. It is not yet a useful answer for a user. The answer becomes concrete when you can name the Ethereum transaction, open it in an explorer, inspect its receipt, and connect it back to the room that produced it.
That path also explains the room model better than a new vocabulary diagram. The application runs several policy-bound actions. The room produces a checkpoint. Ethereum accepts the canonical result. The room can then continue or close according to its profile. Every claim in that sentence has a different piece of evidence.
- Read the accepted checkpoint transaction hash from the running system.
- Open the same hash through the local Blockscout API and transaction page.
- Match receipt status, block number, and room evidence before calling the checkpoint settled.
Demo / use it today
See an accepted checkpoint in the block explorer
Continue from a running local enclave that has accepted at least one checkpoint. Read the transaction hash from the zkDeal system surface, then ask Blockscout for the receipt and open the human-readable transaction page.
Before you start
- A Bash-compatible shell: Linux, macOS, or WSL on Windows. The copyable commands use POSIX shell syntax.
- The complete local Kurtosis enclave from this series, with at least one accepted checkpoint.
- curl and jq.
- The local coordinator and explorer ports printed by Kurtosis; no public-network credentials are required.
Take the hash from zkDeal
Query the system endpoint and require a full L1 transaction hash. Do not scrape a log fragment or invent a transaction URL from a partial identifier.
Ask the explorer for the same transaction
Use Blockscout’s API to retrieve status, block, method, and hash. The returned hash must match the one reported by the coordinator.
Open the human-readable evidence
Print the transaction page URL last. It is the shareable end of the demo, while the machine-readable checks guard against a friendly page hiding a failed or different transaction.
Name the preserved enclave
ENCLAVE=zkdeal-publicDownload the immutable acceptance evidence
EVIDENCE_DIR="$(mktemp -d)" && \
kurtosis files download "$ENCLAVE" zkdeal-v5-kurtosis-evidence "$EVIDENCE_DIR" && \
EVIDENCE="$(find "$EVIDENCE_DIR" -name v5-kurtosis-evidence.json -print -quit)"Require proof and settlement evidence
node -e "const e=JSON.parse(require('fs').readFileSync(process.argv[1])); const full=(v)=>/^0x[0-9a-fA-F]{64}$/.test(v); console.log(JSON.stringify({decision:e.decision,imageIdPresent:e.imageId.length>0,journalHashComplete:full(e.journalHash),transactionComplete:full(e.transactions.submit),submitBlock:e.transactions.submitBlock}))" "$EVIDENCE"Expected output shape
{"decision":"VERIFIED","imageIdPresent":true,"journalHashComplete":true,"transactionComplete":true,"submitBlock":"<submit-block>"}Read the exact transaction and explorer endpoint
export TX="$(jq -r .transactions.submit "$EVIDENCE")" \
BLOCK="$(jq -r .transactions.submitBlock "$EVIDENCE")" \
MANAGER="$(jq -r .contracts.manager "$EVIDENCE")" && \
EXPLORER="$(kurtosis port print "$ENCLAVE" explorer http --format ip,number)" && \
export BLOCK MANAGER EXPLORERMatch the exact checkpoint transaction in Blockscout
curl -fsS "http://$EXPLORER/api/v2/transactions/$TX" | jq -c \
'{indexed:(.hash==env.TX),success:((.status|ascii_downcase)=="ok"),managerMatches:(((.to.hash // .to)|ascii_downcase)==(env.MANAGER|ascii_downcase)),blockMatches:((.block_number|tostring)==env.BLOCK)}'Expected output shape
{"indexed":true,"success":true,"managerMatches":true,"blockMatches":true}Print the human-readable transaction page
node -e "console.log('http://' + process.env.EXPLORER + '/tx/' + process.env.TX)"Expected output shape
http://127.0.0.1:3200/tx/<64-hex-checkpoint-transaction>Remove the temporary evidence copy
rm -r -- "$EVIDENCE_DIR" && unset EVIDENCE_DIR EVIDENCE TX BLOCK MANAGER EXPLORERWhat this gives you: You finish with one checkpoint represented three ways—the zkDeal system record, the explorer API response, and a transaction page—all agreeing on the same L1 hash.
Interactive expected I/O
Trace an accepted checkpoint into Blockscout
Select text directly in the player, pause at any point, or copy the complete transcript below.
Copy or read the complete transcript
$ ENCLAVE=zkdeal-public
$ EVIDENCE_DIR="$(mktemp -d)" && \
> kurtosis files download "$ENCLAVE" zkdeal-v5-kurtosis-evidence "$EVIDENCE_DIR" && \
> EVIDENCE="$(find "$EVIDENCE_DIR" -name v5-kurtosis-evidence.json -print -quit)"
$ node -e "const e=JSON.parse(require('fs').readFileSync(process.argv[1])); const full=(v)=>/^0x[0-9a-fA-F]{64}$/.test(v); console.log(JSON.stringify({decision:e.decision,imageIdPresent:e.imageId.length>0,journalHashComplete:full(e.journalHash),transactionComplete:full(e.transactions.submit),submitBlock:e.transactions.submitBlock}))" "$EVIDENCE"
{"decision":"VERIFIED","imageIdPresent":true,"journalHashComplete":true,"transactionComplete":true,"submitBlock":"<submit-block>"}
$ export TX="$(jq -r .transactions.submit "$EVIDENCE")" \
> BLOCK="$(jq -r .transactions.submitBlock "$EVIDENCE")" \
> MANAGER="$(jq -r .contracts.manager "$EVIDENCE")" && \
> EXPLORER="$(kurtosis port print "$ENCLAVE" explorer http --format ip,number)" && \
> export BLOCK MANAGER EXPLORER
$ curl -fsS "http://$EXPLORER/api/v2/transactions/$TX" | jq -c \
> '{indexed:(.hash==env.TX),success:((.status|ascii_downcase)=="ok"),managerMatches:(((.to.hash // .to)|ascii_downcase)==(env.MANAGER|ascii_downcase)),blockMatches:((.block_number|tostring)==env.BLOCK)}'
{"indexed":true,"success":true,"managerMatches":true,"blockMatches":true}
$ node -e "console.log('http://' + process.env.EXPLORER + '/tx/' + process.env.TX)"
http://127.0.0.1:3200/tx/<64-hex-checkpoint-transaction>
$ rm -r -- "$EVIDENCE_DIR" && unset EVIDENCE_DIR EVIDENCE TX BLOCK MANAGER EXPLORERVideo fallback generated with VHS 0.11.0
Pinned public inputs
Repositories and images used here
Public availability is not one license claim: protocol, examples, and testing are MIT; node, prover, and coordinator are public source under BUSL-1.1.