Kailua
This document is a guide to the design, implementation, and usage of RISC Zero's Kailua.
Introduction
Kailua is suite of tools and contracts for upgrading Optimistic rollups to use ZK Fault Proofs powered by the RISC Zero zkVM. Kailua introduces its own novel fault proof game design which provides the best in class security guarantees for sequencing rollup transactions. These benefits come at marginal added operational costs compared to full validity proving.
Withdrawal Delay
A delay attack happens when a dishonest party attempts to delay the withdrawal finality of correctly sequenced transactions. For optimistic rollups, the main attack vector is through triggering on-chain disputes using the fault proving mechanism.
Kailua's dispute resolution mechanism resolves disputes as fast as proofs can be generated. Thanks to the RISC Zero zkVM's scale-out design, this means that the impact of delay attacks can be mitigated with more proving power. For example, the worst-case single-block dispute requires proving 100bn cycles in the zkVM, a workload that can be computed by RISC Zero's Bonsai service in under an hour.
Denial-of-Service
Assuming an honest majority operates the parent chain of the rollup, on-chain denial-of-service attacks can still happen if a wealthy party raises the on-chain gas costs beyond what honest participants in the fault proof protocol can afford. This block congestion attack can effectively censor disputes against faulty sequencing proposals from being made on-chain, threatening the safety of the rollup.
Kailua's design incorporates "Adaptive Dispute Cutoffs", which delays withdrawal finality to increase the dispute opportunity based on the level of on-chain congestion. This guarantees that if faults cost more to dispute than a predetermined amount, honest parties will be granted more time until gas costs subside.
Sybil Identities
Whale attackers can overwhelm honest parties in a dispute resolution mechanism by using multiple identities to flood the system with disputes. In fault proving schemes where a defender has to issue a timely response on-chain to every dispute, the costs borne by the defender to continuously participate in all open disputes until they are resolved can be overwhelming, leading to some faults slipping through.
Sybil attacks against Kailua force attackers to prove each other's faults at no added cost to the honest defender. The only requirement for safety in Kailua is for an honest party to submit a correct sequencing proposal. The added requirement for liveness is for disputes to be resolved through proofs, which carry no time limit to generate.
Resource Exhaustion
Some fault proof protocols require additional collateral to be staked for every move made in the system, while others require proofs to be generated in a timely manner. These two requirements cause some other systems to be vulnerable to resource exhaustion, where the resource can be the collateral or the proving power required for an honest party to issue a timely response, even if it can afford the transaction fees.
Kailua operates under constant collateral requirements for honest parties, and places no restrictions on proving times, enabling honest parties to successfully defend against attacks of any size at a pre-determined maximum cost.
Quickstart
Kailua enables rollup operators to add a new fault proof system to their rollup via the Optimism DisputeGameFactory
contract.
Kailua's contracts rely on RISC-Zero zkVM proofs to finalize/dismiss output proposals, and are compatible with
Optimism's Bedrock contracts v1.4.0
and above.
Prerequisites
Local Devnet
You can deploy a local optimism devnet equipped with Kailua through the following commands:
just devnet-install
- Fetches
v1.9.1
of theoptimism
monorepo.
- Fetches
just devnet-build
- Builds the local cargo and foundry projects.
just devnet-up
- Starts a local OP Stack devnet using docker.
- Dumps the output into
devnetlog.txt
for inspection.
just devnet-upgrade
- Upgrades the devnet to use the
KailuaGame
contract. - Assumes the default values of the local optimism devnet, but can take parameters.
- Upgrades the devnet to use the
just devnet-propose
- Launches the Kailua proposer.
- This runs the sequences, which periodically creates new
KailuaGame
instances.
just devnet-validate
- Launches the Kailua validator.
- This monitors
KailuaGame
instances for disputes and creates proofs to resolve them. - Note: Use
RISC0_DEV_MODE=1
to use fake proofs.
just devnet-fault
- Deploys a single
KailuaGame
instance with a faulty sequencing proposal. - Tests the validator's fault proving functionality.
- Tests the proposer's canonical chain tracking functionality.
- Deploys a single
- After you're done:
just devnet-down
to stop the running docker containers.just devnet-clean
to cleanup the docker volumes.
Design Overview
Kailua's ZK fault proof game operates seamlessly in two main ways:
- Disputes are non-interactive, removing the need for a "bisection" or multi-round on-chain search for a fault.
- Disputes are implicit between contradictory proposals, removing the need for a special "challenge" transaction.
Sequencing
Sequencing proposals in Kailua can utilize the publication of extra data instead of only the single commitment submitted in other protocols in order to reduce the amount of proving work required to resolve disputes. This extra data consists of commitments to the intermediate sequencing states, which allows the generated ZK proofs to target only a sub-sequence of blocks comprising one transition between the intermediate states instead of the entire proposal.
While Kailua can be configured to operate using a single published commitment per proposal, this may make the proving work required to resolve disputes impractical for chains with very low block times, or a significantly large number of blocks per proposal in general.
--- title: Example Kailua Sequencing Proposal --- graph LR; A -.8.-> B((B)) -.8.-> C((C)) -.8.-> D((D)) -.8.-> E((E)) -.8.-> F((F)) -.8.-> G((G)) -.8.-> H((H)) -.8.-> I;
--- title: Example Standard Sequencing Proposal --- graph LR; A --64--> I;
The above two diagrams illustrate the extended data in Kailua sequencing proposals. While a standard proposal for sequencing 64-blocks would only comprise a single commitment, the Kailua variant here is configured to also require the commitment for every 8th block. In this configuration, any Kailua fault proof would only have to provably derive a sequence of at most 8 blocks.
To save on DA costs, blobs or alternative DA layers can be used to publish intermediate commitments. Moreover, as empty blocks are cheap to prove, an intermediate commitment can be defined to cover at most N empty and at most M non-empty blocks, where N >> M.
Disputes
Each new sequencing proposal implicitly disputes the last existing proposal that contradicts it. Once this happens, a proof is required to demonstrate which of the two contradictory proposals, if any, commits to the correct sequencing state at their first point of divergence. The proof then eliminates one, or both, contradictory proposals, and neither proposals can be finalized until the proof is submitted.
While any new contradictory proposal has to be made within the timeout period of the prior proposal it contradicts, proofs are granted an unlimited amount of time for permissionless submission by anyone.
--- title: Disputes Example --- graph LR; A --> B; A --✓--> B'; A --✓--> B''; B --> C'; B --✓--> C; B' --> C''; C --> D; D --> E; D --✗--> E';
Consider the above example scenario, where proposal A
is finalized, while B
, C
, D
and E
are the only correct sequencing
proposals pending finalization, while all others are invalid.
A plain edge from a parent to a child indicates that the child proposal was made while no contradictory siblings should have existed. A checkmark on the edge indicates that the proposal was made within the timeout period of the contradicotry sibling. A crossmark indicates that the timeout period of the contradictory sibling proposal had expired before the child proposal was introduced.
The following three challenges are the only ones implied:
B'
challengesB
B''
challengesB
(the proof for the prior challenge will eliminateB'
).C
challengesC'
.
The following two invalid proposals created no challenges:
C''
has no siblings and therefore causes no implicit challenges, but will be eliminated once its parentB'
is eliminated.E'
was made after the timeout period forE
had expired, and was automatically eliminated.
In this scenario, B
can only be finalized once two proofs are submitted to resolve its disputes against B'
and B''
.
Proposal C
can only be finalized once a proof resolves its dispute against C'
, and its parent B
is finalized.
D
has no contenders and can be finalized once its parent C
is finalized.
The timeout period for E
had passed before E'
was introduced, and therefore E
can be finalized once its parent D
is finalized.
Project
Kailua's project structure is primarily as follows:
kailua // Root project directory
├── bin
│ ├── cli // Main Kailua CLI
│ ├── client // FPVM Client
│ └── host // FPVM Host
├── book // This document
├── build
│ └── risczero // RISC Zero zkVM proving backend
├── crates
│ ├── common // Fault proving primitives
│ └── contracts // Fault proof contracts
├── justfile // Convenience commands
└── testdata
└── 16491249 // Example FPVM test data for op-sepolia block
CLI
The CLI for Kailua is designed to support five main commands:
config
: Outputs configuration information required for migration.fast-track
: Automatically upgrades an existing rollup deployment to utilize Kailua for fault proving.propose
: Monitor a rollup for sequencing state and publish proposals on-chain (akin to op-proposer).validate
: Monitor a rollup for disputes and publish the necessary FPVM proofs for resolution.fault
: Submit garbage proposals to test fault proving.
Contracts
The contracts directory is a foundry project comprised of the following main contracts:
KailuaTournament.sol
: Logic for resolving disputes between contradictory proposals.KailuaTreasury.sol
: Logic for maintaining collateral and paying out provers for resolving disputes.KailuaGame.sol
: Logic for introducing new sequencing proposals.KailuaLib.sol
: Misc. utilities.
The kailua-contracts
crate builds and exports these contracts in Rust.
FPVM
The Kailua FPVM executes Optimism's Kona
inside the RISC Zero zkVM to derive and execute optimism blocks and create fault proofs.
The following project components work together to enable this functionality:
bin/host
: A modified version ofKona
's host binary, which acts as an oracle for the witness data required to create a fault proof.bin/client
: A modified version ofKona
's client binary, which executes thefpvm
while querying the host for the necessary chain data.build/risczero/fpvm
: The zkVM binary to create ZK fault proofs withKona
.crates/common
: A wrapper crate aroundKona
with utilities for efficient ZK fault proving.
Setup
Make sure to first install the prerequisites from the quickstart section before proceeding.
Installation
Before you can start migrating your rollup, you'll need to build and install Kailua's binaries by calling the following commands from the root project directory:
Do not run these install
commands in parallel.
Each binary installation will take time to reproducibly build the FPVM program in release mode.
If you install them in parallel, GitHub may throttle you, leading to a docker build error.
CLI Binary
cargo install kailua-cli --path bin/cli
Prover Binary
At the cost of longer compilation time, you can embed the RISC Zero prover logic into kailua-host
instead of having
it utilize your locally installed RISC Zero r0vm
.
To do this, add -F prove
to the command below.
cargo install kailua-host --path bin/host
Configuration
Once your installation is successful, you should be able to run the following command to fetch the Kailua configuration parameters for your rollup instance:
kailua-cli config --op-node-url [YOUR_OP_NODE_URL] --op-geth-url [YOUR_OP_GETH_URL] --eth-rpc-url [YOUR_ETH_RPC_URL]
Running the above command against the respective op-sepolia endpoints should produce the following output:
RISC0_VERSION: 1.2.0
FPVM_IMAGE_ID: 0xA1FC2FD8A2EEE54047591648D90D7692D2E2EA9E5F1160CF7575AF2B03E16BBE
CONTROL_ROOT: 0x8CDAD9242664BE3112ABA377C5425A4DF735EB1C6966472B561D2855932C0469
CONTROL_ID: 0x04446E66D300EB7FB45C9726BB53C793DDA407A62E9601618BB43C5C14657AC0
SET_BUILDER_ID: 0x744CCA56CDE6933DEA72752C78B4A6CA894ED620E8AF6437AB05FAD53BCEC40A
RISC_ZERO_VERIFIER: 0x925D8331DDC0A1F0D96E68CF073DFE1D92B69187
GENESIS_TIMESTAMP: 1691802540
BLOCK_TIME: 2
ROLLUP_CONFIG_HASH: 0xF9CDE5599A197A7615D7207E55188D9D1709073A67A8F2D53EB9184400D4FBCD
DISPUTE_GAME_FACTORY: 0x05F9613ADB30026FFD634F38E5C4DFD30A197FA1
OPTIMISM_PORTAL: 0x16FC5058F25648194471939DF75CF27A2FDC48BC
KAILUA_GAME_TYPE: 1337
Make sure that your FPVM_IMAGE_ID
matches the value above.
This value determines the exact program used to prove faults.
If your RISC_ZERO_VERIFIER
value is blank, this means that your rollup might be deployed on a base layer that does
not have a deployed RISC Zero zkVM verifier contract.
This means you might have to deploy your own verifier.
Always revise the RISC Zero documentation
to double-check verifier availability.
Once you have these values you'll need to save them for later use during migration.
Parameters
Before migrating to Kailua, you'll need to decide on a few setup parameters and note them down for later use during the migration process.
Starting Block Number
You'll need to pick a block number for Kailua to start sequencing from.
The sequencing state according to your op-node
at the block you pick will be immediately finalized.
When you choose to enable withdrawal against Kailua sequencing proposals, your users will be able to start withdrawals
using this finalized state.
You can postpone enabling withdrawals using Kailua at any later point in time after successful migration.
Proposal Block Span
Each sequencing proposal in Kailua must cover a fixed number of L2 blocks, which will determine how much data must be published per proposal. Consequently, this parameter will determine your proposer's DA costs for using Kailua.
The current implementation does not yet support mutli-block fault proofs, which means that proposals will have to publish a commitment per covered L2 block in the proposal.
These commitments are published as Blobs, which means you should optimize your block span S
to be S = B * 4096 + 1
,
where B
is the number of blobs required for a single proposal transaction (Ethereum currently limits a single block to
at most 6 blobs, i.e. B < 7
).
Subsequently, combining S
with your rollup's block time determines how often your sequencer has to publish a proposal
to ensure the liveness of your chain.
Consider Optimism Mainnnet as an example, which has a block time of 2 seconds. To keep its current average sequencing frequency of ~55 minutes, it only needs to publish ~1650 commitments per proposal. To maximize the utilization of the extra blob published when proposing, OP Mainnet can relax its proposal rate to once per 2 hours and 15 minutes.
Proposal Time Gap
Because Kailua is designed for permissionless sequencing, it has an extra safety mechanism that can prevent sequencing proposals from being made eagerly before the parent chain data supporting that state is finalized.
This mechanism comes in the form of a forced delay between the timestamp of the L2 block being proposed, and the current timestamp on the parent chain (ethereum).
At the time of writing, Ethereum finalizes each block in approximately 15 minutes.
Consequently, we recommend you set this parameter to 15 × 60 = 900
seconds to match.
While the Kailua proposer agent won't publish a sequencing proposal until it is considered safe, the Kailua contracts allow you to enforce this requirement so that even an eager (potentially dishonest) proposer cannot have a head start!
Collateral Amount
The collateral requirements for a sequencer in Kailua come in the form of a fixed amount to be deposited, independent of how many sequencing proposals are in flight. This is because a malicious Kailua proposer, and any faulty sequencing proposals it has published, is eliminated using only a single fault proof.
The prover who submitted that fault proof consequently gets compensated with the faulty sequencer's staked collateral. This collateral should at least cover the proving cost, but should also include a sizeable tip for the prover to incentivize proving priority. Our estimates put a worst-case proving cost using Bonsai for a single (OP Mainnet) block at $100 USD.
Currently, OP Mainnet requires 0.08 ETH (~$300) of collateral per proposal, and finalizes a proposal after at least 3.5
days if it is undisputed.
This means, at an average hourly rate of proposing, the proposer has 84 * 0.08 = 6.72
ETH (~$3700 USD) on average
locked up as collateral in the best case where no disputes take place.
Using Kailua, 0.08 ETH would be sufficient as the total collateral locked up by the proposer, even under the same finality delay. This would cover the worst-case proving cost in case of dispute, and, discounting transaction costs, leave a $200 tip.
Challenge Timeout
The current implementation of Kailua does not yet have adaptive dispute periods based on congestion. Consequently, you should keep your existing challenge timeout period.
Verifier Contract
RISC Zero maintains a set of pre-deployed verifier contracts for its ZK proving system. These contracts are regularly upgraded to support new releases of the prover, and also have a permissionless fail-safe mechanism that anyone who can produce a proof-of-exploit can trigger to halt the verifier.
You must ensure that the chosen verifier contract supports your RISC Zero zkVM version. Once a new zkVM version is released, there can be a delay in adding it to the router.
You have the choice of either using the already deployed verifier for your parent chain, or deploying and maintaining your own verifier contracts, as described in the later sections.
On-chain Contracts
In order to utilize Kailua, you'll need to deploy the Kailua dispute contracts, and configure your rollup to use them. This process will require access to your rollup's 'Owner' and 'Guardian' wallets.
Overview
The steps required to upgrade your on-chain rollup contracts to support Kailua are as follows:
- (Optional) Deploy a RISC Zero Verifier contract set.
- This can be skipped by using a pre-existing verifier contract.
- Deploy a
KailuaTreasury
and aKailuaGame
contract with your configuration. - Initialize the
KailuaTreasury
contract to mark the start of sequencing under Kailua. - Update the rollup's
DisputeGameFactory
contract to useKailuaGame
for sequencing proposals.- (Optional) Enable withdrawals using finalized Kailua proposals.
The Kailua CLI has a fast-track
command for automating the L1 transactions required to migrate to Kailua.
If the command does not yet support your configuration, you'll need to follow the manual steps in the next sub-sections.
Fast-track Migration
The fast-track migration tool is restricted to certain rollup deployment configurations. As the tool is improved to accommodate more setups, these requirements will be relaxed.
Requirements
- The "Owner" account must be a "Safe" contract instance controlled by a single private-key controlled wallet (EOA).
- The "Guardian" account must be a private-key controlled wallet (EOA).
- You must have access to the raw private key(s) above.
You can skip the guardian key/account requirements if you do not wish to enable withdrawals against sequencing proposals
made by Kailua as part of the fast-track process via the respect-kailua-proposals
flag.
You can enable withdrawals manually later using the OptimismPortal2
contract.
Usage
If all the above conditions are met, you can fast track the migration of your rollup to Kailua as follows:
kailua-cli fast-track \
--eth-rpc-url [YOUR_ETH_RPC_URL] \
--op-geth-url [YOUR_OP_GETH_URL] \
--op-node-url [YOUR_OP_NODE_URL] \
\
--starting-block-number [YOUR_STARTING_BLOCK_NUMBER] \
--proposal-block-span [YOUR_BLOCKS_PER_PROPOSAL] \
--proposal-time-gap [YOUR_PROPOSAL_TIME_GAP] \
\
--collateral-amount [YOUR_COLLATERAL_AMOUNT] \
--verifier-contract [RISC_ZERO_VERIFIER_ADDRESS] \
--challenge-timeout [YOUR_CHALLENGE_PERIOD] \
\
--deployer-key [YOUR_DEPLOYER_KEY] \
--owner-key [YOUR_OWNER_KEY] \
--guardian-key [YOUR_GUARDIAN_KEY] \
\
--respect-kailua-proposals
Endpoints
The first three parameters to this command are the L1 and L2 RPC endpoints:
eth-rpc-url
: The endpoint for the parent chain.op-geth-url
: The endpoint for the rollup execution client.op-node-url
: The endpoint for the rollup consensus client.
Sequencing
The next three parameters configure sequencing:
starting-block-number
: The rollup block number to immediately finalize and start sequencing from.proposal-block-span
: The number of rollup blocks each sequencing proposal must cover.proposal-time-gap
: The minimum amount of time (in seconds) that must pass before a rollup block can be sequenced.
The sequencing state at the block starting-block-number
as reported by the op-node
will be finalized without delay.
Fault Proving
The next three parameters configure fault proving:
collateral-amount
: The amount of collateral (in wei) a sequencer has to stake before publishing proposals.verifier-contract
: (Optional) The address of the existing RISC Zero verifier contract to use. If this argument is omitted, a new set of verifier contracts will be deployed.- If you wish to use an already existing verifier, you must provide this argument, even if the
config
command had located a verifier. - If you are deploying a new verifier contract and wish to support fake proofs generated in dev mode (insecure), make sure to set
RISC0_DEV_MODE=1
in your environment before invoking thefast-track
command.
- If you wish to use an already existing verifier, you must provide this argument, even if the
challenge-timeout
: The timeout (in seconds) for a sequencing proposal to be contradicted.
Ethereum Transactions
The next three parameters are the private keys for the respective parent chain wallets:
deployer-key
: Private key for the EOA used to deploy the new Kailua contracts.owner-key
: Private key for the sole EOA controlling the Owner "Safe" contract.guardian-key
: Private key for the EOA used as the "Guardian" of the optimism portal.
Withdrawals
Changing the respected game type to Kailua may crash the op-proposer
provided by optimism.
This should be inconsequential because you'll need to run the Kailua proposer for further sequencing to take place anyway.
The final argument configures withdrawals in your rollup:
respect-kailua-proposals
: (if present) will allow withdrawals using sequencing proposals finalized by Kailua.
If you've successfully completed fast-track migration using the tool, you may now skip to the Off-chain page.
On-chain Proof Verification
If you've successfully performed fast-track migration, you do not need to follow the steps on this page.
The cryptographic fault proofs generated by Kailua require the existence of a RISC Zero verifier contract on the parent chain (ethereum).
Use the Kailua CLI config
command to retrieve the address of the officially deployed RISC Zero verifier for your
parent chain.
If one is available, you can use that address as your verifier and skip the steps in this section.
This section explains how to deploy a verifier suited to your needs, but you'll need to maintain it in case of adopting any updates to Kailua that change the RISC Zero zkVM version used for proving.
Verifier Contracts
This section describes the contracts that make up the on-chain proof verification pipeline.
Verifier Router
The RISCZeroVerifierRouter contract routes proofs from different sources to their correct verifier. This allows your application (and Kailua) to leverage proofs generated using different zkVM versions, or aggregated through the Boundless proving network, while delegating the complexity of managing the verifier version to the router contract.
Depending on your needs, you may need to deploy and manage your own verifier instead of relying on the pre-deployed router managed by RISC Zero.
The verifier deployment made by Kailua does not yet utilize the Emergency stop contract in the pre-deployed RISC Zero verifier, which allows anyone to permissionlessy disable a verification backend in the router by proving a false statement.
Groth16 Verifier
The RISCZeroGroth16Verifier only accepts valid Groth16 proofs generated using its hardcoded RISC Zero zkVM version determined by the control root and id constructor parameters. This verifier is intended to be deployed and then added as a possible backend to a router instead of being used directly on its own. However, it is possible to call and use this verifier directly if the prover and verifier versions align.
Set Verifier (Boundless Network)
The RISCZeroSetVerifier accepts aggregated proofs, which are generated through recursively verifying other proofs inside an aggregator program. This verifier only verifies "inclusion proofs", and delegates the verification of the cryptographic proof of correct aggregation to another verifier (such as the router or the Groth16 verifier directly). This means it must be paired with another verifier contract.
Fake Proof Verifier (INSECURE)
This verifier accepts fake proofs generated while running the RISC Zero zkVM in "dev mode". It is only useful for testing out the zkVM in a development environment without being delayed by proving time.
Deployment
This section will walk you through creating your own verifier deployment that supports individual and aggregated proofs.
The commands below will be using Foundry's forge
and cast
utilities, which you should have installed as part of the
foundry prerequisite.
The below foundry commands expect both a parameter that determines the wallet to use and the rpc endpoint of the parent
chain.
You will have to add these two parameters manually to every command below.
For more information, refer to forge create --help
, cast call --help
, and cast send --help
First, change your working directory to crates/contracts/foundry
for forge
to work:
cd crates/contracts/foundry
Router
constructor(address admin) Ownable(admin)
The RISCZeroVerifierRouter
constructor requires a single admin
address, which is an account authorised to modify
the router in one of two ways after it is deployed:
- Add a new verification backend through
addVerifier
: - Permanently disable a verification backend through
removeVerifier
:
To deploy a new router, invoke the following command
forge create RiscZeroVerifierRouter --constructor-args [ADMIN_ADDRESS]
On success, you should see output similar to the following:
Deployer: [YOUR_DEPLOYER_WALLET_ADDRESS]
Deployed to: [YOUR_DEPLOYED_ROUTER_CONTRACT]
Transaction hash: [YOUR_DEPLOYMENT_TRANSACTION_HASH]
Make sure to note down the YOUR_DEPLOYED_ROUTER_CONTRACT
address.
We will use this in the following commands when adding proving backends.
The router cannot verify any proofs on its own.
Aggregate Verifier
constructor(IRiscZeroVerifier verifier, bytes32 imageId, string memory _imageUrl)
The aggregate verifier requires two main parameters to construct it, an address for a verifier to use to validate proofs of aggregation, and an image id defining the program to use for aggregating proofs. The third parameter specifies where the aggregation program is hosted, and can be left blank.
We will reuse the router contract we just deployed as the verifier, and the SET_BUILDER_ID
value we got from running
kailua-cli config
.
To deploy a new aggregate verifier
forge create RiscZeroSetVerifier --constructor-args \
[YOUR_DEPLOYED_ROUTER_CONTRACT] \
[SET_BUILDER_ID] \
""
On success, you should see output similar to the following:
Deployer: [YOUR_DEPLOYER_WALLET_ADDRESS]
Deployed to: [YOUR_DEPLOYED_AGGREGATE_VERIFIER_CONTRACT]
Transaction hash: [YOUR_DEPLOYMENT_TRANSACTION_HASH]
The next step is to now add this aggregate verifier contract as a backend for our router to use to verify any aggregated
proofs it receives.
For this, we will first to need to query the aggregate verifier for its "selector" using foundry's cast
utility:
cast call \
[YOUR_DEPLOYED_AGGREGATE_VERIFIER_CONTRACT] \
"SELECTOR() returns (bytes4)"
This should return a short string similar to the following:
0x9cc26c32
We can now use this selector to add the aggregate verifier to the router using the admin
wallet you specified while
deploying the router:
cast send \
[YOUR_DEPLOYED_ROUTER_CONTRACT] \
"addVerifier(bytes4 selector, address verifier)" \
[YOUR_AGGREGATE_VERIFIER_SELECTOR] \
[YOUR_DEPLOYED_AGGREGATE_VERIFIER_CONTRACT]
The output from successfully issuing this transaction should resemble the following:
blockHash 0x9cb7f77cab555ff8907a62d19165795e7dbd51d558ee29a7383ced32daea18ab
blockNumber 821
contractAddress
cumulativeGasUsed 414546
effectiveGasPrice 1000000007
from 0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc
gasUsed 46831
logs []
logsBloom 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
root
status 1 (success)
transactionHash 0x1446eeeb02008e6ef37dc60556f6a45848f106e175d0ea597fc41370918022c9
transactionIndex 1
type 2
blobGasPrice
blobGasUsed
authorizationList
to 0x0116686E2291dbd5e317F47faDBFb43B599786Ef
Make sure that the status field in your output indicates success!
You've now connected your verifier router to the aggregate verifier. However, this pair still cannot verify any proofs on its own! Next, we will install a cryptographic verifier for this task.
Groth16 Verifier
The Groth16 verifier validates stand-alone cryptographic proofs generated using the RISC Zero zkVM and compressed using the RISC Zero STARK-to-SNARK wrapper.
This verifier can be deployed as follows using the control root and id from the kailua-cli config
command output:
forge create RiscZeroGroth16Verifier --constructor-args \
[YOUR_CONTROL_ROOT] \
[YOUR_CONTROL_ID]
The output should again give you the relevant addresses:
Deployer: [YOUR_DEPLOYER_WALLET_ADDRESS]
Deployed to: [YOUR_DEPLOYED_GROTH16_VERIFIER_CONTRACT]
Transaction hash: [YOUR_DEPLOYMENT_TRANSACTION_HASH]
We again need to query this verifier's selector:
cast call [YOUR_DEPLOYED_GROTH16_VERIFIER_CONTRACT] \
"SELECTOR() returns (bytes4)"
Yielding another 4-byte selector:
0xc101b42b
And finally we need to add this verifier to our router:
cast send \
[YOUR_DEPLOYED_ROUTER_CONTRACT] \
"addVerifier(bytes4 selector, address verifier)" \
[YOUR_GROTH16_SELECTOR] \
[YOUR_DEPLOYED_GROTH16_VERIFIER_CONTRACT]
You now have a RISC Zero verifier contract for stand-alone and aggregated ZK (fault) proofs!
On-chain Dispute Resolution
If you've successfully performed fast-track migration, you do not need to follow the steps on this page.
Kailua's on-chain dispute mechanism is powered by its own custom contracts that define a novel ZK dispute game. Each rollup has to deploy its own pair of dispute resolution contracts, and this section will guide you through that process.
The commands below will be using Foundry's forge
and cast
utilities, which you should have installed as part of the
foundry prerequisite.
The below foundry commands expect both a parameter that determines the wallet to use and the rpc endpoint of the parent
chain.
You will have to add these two parameters manually to every command below.
For more information, refer to forge create --help
, cast call --help
, and cast send --help
First, change your working directory to crates/contracts/foundry
for forge
to work:
cd crates/contracts/foundry
KailuaTreasury
constructor(
IRiscZeroVerifier _verifierContract,
bytes32 _imageId,
bytes32 _configHash,
uint256 _proposalBlockCount,
GameType _gameType,
IDisputeGameFactory _disputeGameFactory
)
This contract stores the collateral bonds required for sequencers to publish their proposal, and also stores the first sequencing proposal for Kailua as a fault dispute game in your rollup.
Deployment
Deployment of this contract is via the command below:
forge create KailuaTreasury --constructor-args \
[YOUR_RISC_ZERO_VERIFIER] \
[YOUR_FPVM_IMAGE_ID] \
[YOUR_ROLLUP_CONFIG_HASH] \
[YOUR_PROPOSAL_BLOCK_COUNT] \
[YOUR_KAILUA_GAME_TYPE] \
[YOUR_DISPUTE_GAME_FACTORY]
Deploying the contract successfully should yield similar output to the following:
Deployer: [YOUR_DEPLOYER_WALLET_ADDRESS]
Deployed to: [YOUR_DEPLOYED_TREASURY_CONTRACT]
Transaction hash: [YOUR_DEPLOYMENT_TRANSACTION_HASH]
Take note of the contract address since we'll need it later.
Configuration
Once deployed, you'll need to set the bond value (in wei) required for sequencers.
This is done by calling the setParticipationBond
function on the treasury contract using the owner
wallet for your
rollup.
For example, if your bond value is 12 eth, first convert this to wei using cast
:
cast to-wei 12
12000000000000000000
Then, configure the bond as follows using the rollup owner
wallet:
cast send \
[YOUR_DEPLOYED_TREASURY_CONTRACT] \
"setParticipationBond(uint256 amount)" \
12000000000000000000
If your rollup owner
account is controlled by a Safe
contract, or some other multi-sig contract, you can use
cast calldata
to get the necessary input that your wallet contract should forward.
KailuaGame
constructor(
IKailuaTreasury _kailuaTreasury,
IRiscZeroVerifier _verifierContract,
bytes32 _imageId,
bytes32 _configHash,
uint256 _proposalBlockCount,
GameType _gameType,
IDisputeGameFactory _disputeGameFactory,
uint256 _genesisTimeStamp,
uint256 _l2BlockTime,
uint256 _proposalTimeGap,
Duration _maxClockDuration
)
This contract is used by the optimism DisputeGameFactory
to instantiate every Kailua sequencing proposal after the
initial one in the KailuaTreasury
.
Deployment is fairly similar to the treasury via the command below:
forge create KailuaGame --evm-version cancun --constructor-args \
[YOUR_DEPLOYED_TREASURY_CONTRACT] \
[YOUR_RISC_ZERO_VERIFIER] \
[YOUR_FPVM_IMAGE_ID] \
[YOUR_ROLLUP_CONFIG_HASH] \
[YOUR_PROPOSAL_BLOCK_COUNT] \
[YOUR_KAILUA_GAME_TYPE] \
[YOUR_DISPUTE_GAME_FACTORY] \
[YOUR_GENESIS_TIMESTAMP] \
[YOUR_BLOCK_TIME] \
[YOUR_PROPOSAL_TIME_GAP] \
[YOUR_MAX_CLOCK_DURATION]
Deploying the contract successfully should yield similar output to the following:
Deployer: [YOUR_DEPLOYER_WALLET_ADDRESS]
Deployed to: [YOUR_DEPLOYED_GAME_CONTRACT]
Transaction hash: [YOUR_DEPLOYMENT_TRANSACTION_HASH]
Note down this contract's address, we'll use it later. There is no configuration needed for this contract.
You now have two Kailua dispute resolution contracts tailored to your rollup and ZK verifier!
On-chain State Anchoring
If you've successfully performed fast-track migration, you do not need to follow the steps on this page.
In this section you will be integrating the KailuaTreasury
contract with your rollup's DisputeGameFactory
.
This will finalize the initial sequencing proposal from which Kailua will start.
The commands below will be using Foundry's cast
utility, which you should have installed as part of the
foundry prerequisite.
The below foundry commands expect both a parameter that determines the wallet to use and the rpc endpoint of the parent
chain.
You will have to add these two parameters manually to every command below.
For more information, refer to cast call --help
, and cast send --help
If your rollup owner
account is controlled by a Safe
contract, or some other multi-sig contract, you can use
cast calldata
to get the necessary input that your wallet contract should forward.
Clear DGF Kailua Bond
Optimism's DisputeGameFactory
is design to require a bond value for each sequencing proposal.
The KailuaTreasury
instead requires a constant bond value for a sequencer to make any number of proposals.
To ensure that the Kailua sequencer operates as expected, we will need to set this value to zero for Kailua proposals
if it is non-zero.
You can check the value as follows:
cast call [YOUR_DISPUTE_GAME_FACTORY] \
"initBonds(uint32) returns (uint256)" \
[YOUR_KAILUA_GAME_TYPE]
If the returned value is non-zero, you must reset it through setInitBond
using your rollup owner
wallet:
cast send [YOUR_DISPUTE_GAME_FACTORY] \
"setInitBond(uint32, uint256)" \
[YOUR_KAILUA_GAME_TYPE] \
0
Set KailuaTreasury Implementation
The next step is to update the implementation for the Kailua game type stored in the DisputeGameFactory
contract to
point towards the KailuaTreasury
contract deployed in the last section.
This can be done as follows using your owner
wallet:
cast send [YOUR_DISPUTE_GAME_FACTORY] \
"setImplementation(uint32, address)" \
[YOUR_KAILUA_GAME_TYPE] \
[YOUR_DEPLOYED_TREASURY_CONTRACT]
Anchor Instantiation
Once the implementation is set, the next step is to create a dispute game instance using the treasury. This step is only to be done once in order to create a starting point for sequencing using Kailua.
This step will publish and immediately resolve (finalize) a single sequencing proposal with no chance for dispute.
First, you will need to choose the rollup block number from which Kailua sequencing should start.
Then, you need to query your op-node
for the outputRoot
at that block number as follows:
cast rpc --rpc-url [YOUR_OP_NODE_ADDRESS] \
"optimism_outputAtBlock" \
$(cast 2h [YOUR_STARTING_L2_BLOCK_NUMBER])
Once you have the outputRoot
value you wish to start sequencing from, the next step is to call create
on DisputeGameFactory
using the owner
wallet:
cast send [YOUR_DISPUTE_GAME_FACTORY] \
"create(uint32, bytes32, bytes)" \
[YOUR_KAILUA_GAME_TYPE] \
[YOUR_OUTPUT_ROOT] \
$(cast abi-encode --packed "f(uint64)" [YOUR_STARTING_L2_BLOCK_NUMBER])
To get the address of this new game instance, use the games
function on the DisputeGameFactory
:
cast call [YOUR_DISPUTE_GAME_FACTORY] \
"games(uint32, bytes32, bytes) returns (address, uint64)" \
[YOUR_KAILUA_GAME_TYPE] \
[YOUR_OUTPUT_ROOT] \
$(cast abi-encode --packed "f(uint64)" [YOUR_STARTING_L2_BLOCK_NUMBER])
With this instance address, the last step is to call resolve()
on it using the owner
wallet:
cast send [YOUR_GAME_INSTANCE_ADDRESS] \
"resolve()"
On-chain Sequencing Proposal
If you've successfully performed fast-track migration, you do not need to follow the steps on this page.
In this section you will be integrating the KailuaGame
contract with your rollup's DisputeGameFactory
.
This will allow Kailua sequencers to submit new proposals!
The commands below will be using Foundry's cast
utility, which you should have installed as part of the
foundry prerequisite.
The below foundry commands expect both a parameter that determines the wallet to use and the rpc endpoint of the parent
chain.
You will have to add these two parameters manually to every command below.
For more information, refer to cast call --help
, and cast send --help
If your rollup owner
account is controlled by a Safe
contract, or some other multi-sig contract, you can use
cast calldata
to get the necessary input that your wallet contract should forward.
Set KailuaGame Implementation
The next step is to update the implementation for the Kailua game type stored in the DisputeGameFactory
contract to
point towards the KailuaGame
contract deployed previously.
This can be done as follows using your owner
wallet:
cast send [YOUR_DISPUTE_GAME_FACTORY] \
"setImplementation(uint32, address)" \
[YOUR_KAILUA_GAME_TYPE] \
[YOUR_DEPLOYED_GAME_CONTRACT]
Enable Withdrawals (Optional)
To enable your users to perform withdrawals using Kailua sequencing proposals, you will need to call
setRespectedGameType
on your OptimismPortal2
contract using your guardian
wallet.
This action may cause your optimism op-proposer
agent to crash.
However, you will later run the Kailua proposer agent for sequencing anyway.
cast send [YOUR_OPTIMISM_PORTAL] \
"setRespectedGameType(uint32)" \
[YOUR_KAILUA_GAME_TYPE]
Off-chain Agents
Once your chain contracts are upgraded to integrate Kailua, this section describes what you need to do for sequencing
and fault proving to take place in your rollup using Kailua.
Kailua provides two agents to take on the role of the standard Optimism op-proposer
and op-challenger
agents.
If you will only be using Kailua for sequencing (and withdrawals), you should terminate your op-proposer
and
op-challenger
agent processes if you plan on reusing their wallets to avoid transaction errors.
Just like their optimism counterparts, the Kailua agents must remain online and their wallets sufficiently funded to guarantee the safety and liveness of your rollup.
Kailua currently only supports permissionless sequencing. This means that anyone can run these Kailua agents locally for your rollup.
Kailua Proposer
The Kailua proposer agent takes care of publishing your local op-node
's view of transaction sequencing to Ethereum in
a format that is compatible with the Kailua ZK fault dispute mechanism.
It also attempts to resolve any finalizeable proposals.
Usage
Starting the Kailua proposer is straightforward:
kailua-cli propose \
--eth-rpc-url [YOUR_ETH_RPC_URL] \
--beacon-rpc-url [YOUR_BEACON_RPC_URL] \
--op-geth-url [YOUR_OP_GETH_URL] \
--op-node-url [YOUR_OP_NODE_URL] \
--data-dir [YOUR_PROPOSER_DATA_CACHE_PATH] \
--proposer-key [YOUR_PROPOSER_WALLET_PRIVATE_KEY]
### Endpoints
The first four arguments specify the endpoints that the proposer should use for sequencing:
* `eth-rpc-url`: The parent chain (ethereum) endpoint for reading/publishing proposals.
* `beacon-rpc-url`: The DA layer (eth-beacon chain) endpoint for retrieving published proposal data.
* `op-geth-url`: The rollup `op-geth` endpoint to read configuration data from.
* `op-node-url`: The rollup `op-node` endpoint to read sequencing proposals from.
Cache Directory (Optional)
The proposer saves data to disk as it tracks on-chain proposals. This allows it to restart quickly without requesting a lot of old on-chain data if terminated.
data-dir
: Optional directory to save data to.- If unspecified, a tmp directory is created.
Wallet
The proposer requires a funded wallet to be able to publish new sequencing proposals on-chain.
proposer-key
: The private key for the proposer wallet.
The Kailua proposer wallet is critical for security. You must keep your proposer's wallet well funded to guarantee the safety and liveness of your rollup.
Proposal Data Availability
By default, Kailua uses the beacon chain to publish blobs that contain the extra data required for proposals.
Kailua Validator
The Kailua validator watches your rollup for sequencing proposals that contradict each other and generates a ZK fault proof to settle the dispute between them.
The Kailua validator agent requires access to an archive op-geth
rollup node to retrieve data during proof generation.
Node software other than op-geth
is not as reliable for the necessary debug
namespace rpc calls.
Usage
Starting the Kailua validator is straightforward:
kailua-cli validate \
--eth-rpc-url [YOUR_ETH_RPC_URL] \
--beacon-rpc-url [YOUR_BEACON_RPC_URL] \
--op-geth-url [YOUR_OP_GETH_URL] \
--op-node-url [YOUR_OP_NODE_URL] \
--kailua-host [YOUR_KAILUA_HOST_BINARY_PATH] \
--validator-key [YOUR_PROPOSER_WALLET_PRIVATE_KEY]
Endpoints
The first four arguments specify the endpoints that the validator should use to generate fault proofs:
eth-rpc-url
: The parent chain (ethereum) endpoint for reading proposals and publishing proofs.beacon-rpc-url
: The DA layer (eth-beacon chain) endpoint for retrieving rollup data.op-geth-url
: The (archive) rollupop-geth
endpoint to read fault proving witness data from.op-node-url
: The rollupop-node
endpoint to read sequencing proposals from.
Prover
To create a fault proof, the validator invokes the kailua-host
binary.
kailua-host
: The path to thekailua-host
binary to call for proof generation.
Wallet
The validator requires a funded wallet to be able to publish fault proofs on chain.
validator-key
: The private key for the validator wallet.
You must keep your validator's wallet well funded to guarantee the liveness of your rollup and prevent faulty proposals from delaying the finality of honest sequencing proposals.
Running kailua-cli validate
should monitor your rollup for disputes and generate the required proofs!
Delegated Proof Generation
Several extra parameters and environment variables can be specified to determine exactly where the RISC Zero proof generation takes place. Running using only the parameters above will generate proofs using the local RISC Zero prover available to the validator. Alternatively, proof generation can be delegated to an external service such as Bonsai, or to the decentralized Boundless proving network.
All data required to generate the proof can be publicly derived from the public chain data available for your rollup, making this process safe to delegate.
Bonsai
Enabling proving using Bonsai requires you to set the following two environment variables before running the validator:
BONSAI_API_KEY
: Your Bonsai API key.BONSAI_API_URL
: Your Bonsai API url.
Running kailua-cli validate
with these two environment variables should now delegate all validator proving to Bonsai!
Boundless
When delegating generation of Kailua Fault proofs to the decentralized Boundless proving network, for every fault proof, a proof request is submitted to the network, where it goes through the standard proof life-cycle on boundless, before being published by your validator to settle a dispute.
This functionality requires some additional parameters when starting the validator. These parameters can be passed in as CLI arguments or set as environment variables
Proof Requests
The following first set of parameters determine where/how requests are made:
boundless_rpc_url
: The rpc endpoint of the L1 chain where the Boundless network is deployed.boundless_wallet_key
: The wallet private key to use to send proof request transactions.boundless_offchain
: (Optional) Flag instructing whether to submit proofs off-chain.boundless_order_stream_url
: (Optional) The URL to use for off-chain order submission.boundless_set_verifier_address
: The address of the RISC Zero verifier supporting aggregated proofs for order validation.boundless_market_address
: The address of the Boundless market contract.boundless_lookback
: (Defaults to5
) The number of previous proof requests to inspect for duplicates before making a new proof request.
Storage Provider
The below second set of parameters determine where the proven executable and its input are stored:
storage_provider
: One ofs3
,pinata
, orfile
.s3_access_key
: Thes3
access key.s3_secret_key
: Thes3
secret key.s3_bucket
: Thes3
bucket.s3_url
: Thes3
url.aws_region
: Thes3
region.pinata_jwt
: The privatepinata
jwt.pinata_api_url
: Thepinata
api URL.ipfs_gateway_url
: Thepinata
gateway URL.file_path
: The file storage provider path.
Running kailua-cli validate
with the above extra arguments should now delegate all validator proving to the Boundless proving network!