Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
932a9bc9
Unverified
Commit
932a9bc9
authored
Sep 04, 2023
by
Adrian Sutton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add initial documentation for fault proof alpha.
parent
9f926a60
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
307 additions
and
0 deletions
+307
-0
README.md
docs/README.md
+1
-0
README.md
docs/fault-proof-alpha/README.md
+16
-0
cannon.md
docs/fault-proof-alpha/cannon.md
+92
-0
deployments.md
docs/fault-proof-alpha/deployments.md
+24
-0
manual.md
docs/fault-proof-alpha/manual.md
+110
-0
run-challenger.md
docs/fault-proof-alpha/run-challenger.md
+64
-0
No files found.
docs/README.md
View file @
932a9bc9
...
...
@@ -6,3 +6,4 @@ The directory layout is divided into the following sub-directories.
-
[
`postmortems/`
](
./postmortems/
)
: Timestamped post-mortem documents.
-
[
`security-reviews`
](
./security-reviews/
)
: Audit summaries and other security review documents.
-
[
`fault-proof-alpha`
](
./fault-proof-alpha
)
: Information on the alpha version of the fault proof system.
docs/fault-proof-alpha/README.md
0 → 100644
View file @
932a9bc9
## Fault Proofs Alpha
The fault proof alpha is a pre-release version of the OP Stack fault proof system.
This documentation provides an overview of the system and instructions on how to help
test the fault proof system.
The overall design of this system along with the APIs and interfaces it exposes are not
finalized and may change without notice.
### Contents
*
Overview
*
Deployment Details
*
[
Manual Usage
](
./manual.md
)
*
[
Creating Traces with Cannon
](
./cannon.md
)
*
[
Automation with `op-challenger`
](
./run-challenger.md
)
docs/fault-proof-alpha/cannon.md
0 → 100644
View file @
932a9bc9
## Generate Traces with `cannon` and `op-program`
Normally,
`op-challenger`
handles creating the required traces as part of responding to games. However, for manual
testing it may be useful to manually generate the trace. This can be done by running
`cannon`
directly.
### Prerequisites
-
The cannon pre-state downloaded from
[
Goerli deployment
](
./deployments.md#goerli
)
.
-
A Goerli L1 node.
-
An archive node is not required.
-
Public RPC providers can be used, however a significant number of requests will need to be made which may exceed
rate limits for free plans.
-
An OP-Goerli L2 archive node with
`debug`
APIs enabled.
-
An archive node is required to ensure world-state pre-images remain available.
-
Public RPC providers are generally not usable as they don’t support the
`debug_dbGet`
RPC method.
### Compilation
To compile the required programs, in the top level of the monorepo run:
```
bash
make cannon-prestate
```
This will compile the
`cannon`
executable to
`cannon/bin/cannon`
as well as the
`op-program`
executable used to fetch
pre-image data to
`op-program/bin/op-program`
.
### Run Cannon
To run cannon to generate a proof use:
```
bash
mkdir
-p
temp/cannon/proofs temp/cannon/snapshots temp/cannon/preimages
./cannon/bin/cannon run
\
--pprof
.cpu
\
--info-at
'%10000000'
\
--proof-at
'=<TRACE_INDEX>'
\
--stop-at
'=<STOP_INDEX>'
\
--proof-fmt
'temp/cannon/proofs/%d.json'
\
--snapshot-at
'%1000000000'
\
--snapshot-fmt
'temp/cannon/snapshots/%d.json.gz'
\
--input
<PRESTATE>
\
--output
temp/cannon/stop-state.json
\
--
\
./op-program/bin/op-program
\
--network
goerli
\
--l1
<L1_URL>
\
--l2
<L2_URL>
\
--l1
.head <L1_HEAD>
\
--l2
.claim <L2_CLAIM>
\
--l2
.head <L2_HEAD>
\
--l2
.blocknumber <L2_BLOCK_NUMBER>
\
--datadir
temp/cannon/preimages
\
--log
.format terminal
\
--server
```
The placeholders are:
-
`<TRACE_INDEX>`
the index in the trace to generate a proof for
-
`<STOP_INDEX>`
the index to stop execution at. Typically this is one instruction after
`<TRACE_INDEX>`
to stop as soon
as the required proof has been generated.
-
`<PRESTATE>`
the prestate.json downloaded above. Note that this needs to precisely match the prestate used on-chain so
must be the downloaded version and not a version built locally.
-
`<L1_URL>`
the Goerli L1 JSON RPC endpoint
-
`<L2_URL>`
the OP-Goerli L2 archive node JSON RPC endpoint
-
`<L1_HEAD>`
the hash of the L1 head block used for the dispute game
-
`<L2_CLAIM>`
the output root immediately prior to the disputed root in the L2 output oracle
-
`<L2_HEAD>`
the hash of the L2 block that
`<L2_CLAIM>`
is from
-
`<L2_BLOCK_NUMBER>`
the block number that
`<L2_CLAIM>`
is from
The generated proof will be stored in the
`temp/cannon/proofs/`
directory. The hash to use as the claim value is
the
`post`
field of the generated proof which provides the hash of the cannon state witness after execution of the step.
Since cannon can be very slow to execute, the above command uses the
`--snapshot-at`
option to generate a snapshot of
the cannon state every 1000000000 instructions. Once generated, these snapshots can be used as the
`--input`
to begin
execution at that step rather than from the very beginning. Generated snapshots are stored in
the
`temp/cannon/snapshots`
directory.
See
`./cannon/bin/cannon --help`
for further information on the options available.
### Trace Extension
Fault dispute games always use a trace with a fixed length of
`2 ^ MAX_GAME_DEPTH`
. The trace generated by
`cannon`
stops when the client program exits, so this trace must be extended by repeating the hash of the final state in the
actual trace for all remaining steps. Cannon does not perform this trace extension automatically.
If cannon stops execution before the trace index you requested a proof at, it simply will not generate a proof. When it
stops executing, it will write its final state to
`temp/cannon/stop-state.json`
(controlled by the
`--output`
option).
The
`step`
field of this state contains the last step cannon executed. Once the final step is known, rerun cannon to
generate the proof at that final step and use the
`post`
hash as the claim value for all later trace indices.
docs/fault-proof-alpha/deployments.md
0 → 100644
View file @
932a9bc9
## Fault Proof Alpha Deployment Information
### Goerli
Information on the fault proofs alpha deployment to Goerli is not yet available.
### Local Devnet
The local devnet includes a deployment of the fault proof alpha. To start the devnet, in the top level of this repo,
run:
```
bash
make devnet-up
```
| Input | Value |
|----------------------|-------------------------------------------------------------|
| Dispute Game Factory | Run
`jq -r .DisputeGameFactoryProxy .devnet/addresses.json`
|
| Absolute Prestate |
`op-program/bin/prestate.json`
|
| Max Depth | 30 |
| Max Game Duration | 1200 (20 minutes) |
See the
[
op-challenger README
](
../../op-challenger#running-with-cannon-on-local-devnet
)
for information on
running
`op-challenger`
against the local devnet.
docs/fault-proof-alpha/manual.md
0 → 100644
View file @
932a9bc9
## Manual Fault Proof Interactions
## Creating a Game
The process of disputing an output root starts by creating a new dispute game. There are conceptually three key inputs
required for a dispute game:
-
The output root being disputed
-
The agreed output root the derivation process will start from
-
The L1 head block that defines the canonical L1 chain containing all required batch data to perform the derivation
The creator of the game selects the output root to dispute. It is identified by its L2 block number which can be used to
look up the full details in the L2 output oracle.
The agreed output root is defined as the output root immediately prior to the disputed output root in the L2 output
oracle. Therefore, a dispute game should only be created for the first invalid output root. If it is successfully
disputed, all output roots after it would be considered invalid by inference.
The L1 head block can be any L1 block where the disputed output root is present in the L2 output oracle. Proposers
should therefore ensure that all batch data has been submitted to L1 before submitting a proposal. The L1 head block is
recorded in the
`BlockOracle`
and then referenced by its block number.
Creating a game requires two separate transactions. First the L1 head block is recorded in the
`BlockOracle`
by calling
its
`checkpoint`
function. This record the parent of the block the transaction is included in. The
`BlockOracle`
emits a
log
`Checkpoint(blockNumber, blockHash, childTimestamp)`
.
Now the L1 head, along with the information on the output roots from the L2 output oracle can be used to execute cannon
and determine the root claim to use when creating the game. In simple cases, where the claim is expected to be
incorrect, an arbitrary hash can be used for claim values. For more advanced cases
[
cannon can be used
](
./cannon.md
)
to
generate a trace, including the claim values to use at specific steps. Note that it is not valid to create a game that
disputes an output root, using the final hash from a trace that confirms the output root is valid. To dispute an output
root successfully, the trace must resolve that the disputed output root is invalid.
The game can then be created by calling the
`create`
method on the
`DisputeGameFactory`
contract. This requires three
parameters:
-
`gameType`
- a
`uint8`
representing the type of game to create. For fault dispute games using cannon and op-program
traces, the game type is 0.
-
`rootClaim`
- a
`bytes32`
hash of the final state from the trace.
-
`extraData`
- arbitrary bytes which are used as the initial inputs for the game. For fault dispute games using cannon
and op-program traces, this is the abi encoding of
`(uint256(l2_block_number), uint256(l1_checkpoint))`
.
-
`l2_block_number`
is the L2 block number from the output root being disputed
-
`l1_checkpoint`
is the L1 block number recorded by the
`BlockOracle`
checkpoint
This emits a log event
`DisputeGameCreated(gameAddress, gameType, rootClaim)`
where
`gameAddress`
is the address of the
newly created dispute game.
A simple helper script,
[
create_game.sh
](
../../op-challenger#create_gamesh
)
has been created to easily create a new
dispute game and also provides an example of using
`cast`
to manually create a game.
## Performing Moves
The dispute game progresses by actors by countering existing claims via either the
`attack`
or
`defend`
methods in
the
`FaultDisputeGame`
contract. Note that only
`attack`
can be used to counter the root claim. In both cases, there are
two inputs required:
-
`parentIndex`
- the index in the claims array of the parent claim that is being countered
-
`claim`
- a
`bytes32`
hash of the state at the trace index corresponding to the new claim’s position.
A simple helper script,
[
move.sh
](
../../op-challenger#movesh
)
, has been created to easily perform moves and also
provides an example of using
`cast`
to manually call
`attack`
and
`defend`
.
## Performing Steps
Attack and defend can only be used until the maximum depth of the game is reached. To counter claims at the maximum
depth, a step must be performed instead. Calling the
`step`
method in the
`FaultDisputeGame`
contract counters a claim
at the maximum depth by running a single step of the cannon VM on chain. The
`step`
method will revert unless the cannon
execution confirms the claim being countered is invalid.
The inputs for step are:
-
`claimIndex`
- the index in the claims array of the claim that is being countered
-
`isAttack`
- Similar to regular moves, steps can either be attacking or defending
-
`stateData`
- the full cannon state witness to use as the starting state for execution
-
`proof`
- the additional proof data for the state witness required by cannon to perform the step
When a step is attacking, the caller is making the claim that the claim at
`claimIndex`
is incorrect, and the claim for
the previous trace index (made at a previous level in the game) was correct. The
`stateData`
must be the pre-image for
the agreed correct hash at the previous trace index. The call to
`step`
will revert if the post-state from cannon
matches the claim at
`claimIndex`
since the on-chain execution has proven the claim correct and it should not be
countered.
When a step is defending, the caller is making the claim that the claim at
`claimIndex`
is correct, and the claim for
the next trac index (made at a previous level in the game) is incorrect. The
`stateData`
must be the pre-image for the
hash in the claim at
`claimIndex`
.
The
`step`
function will revert with
`ValidStep()`
if the cannon execution proves that the claim attempting to be
countered is correct. As a result, claims at the maximum game depth can only be countered by a valid execution of the
single instruction in cannon running on-chain.
### Populating the Pre-image Oracle
When the instruction to be executed as part of a
`step`
call reads from some pre-image data, that data must be loaded
into the pre-image oracle prior to calling
`step`
.
For
[
local pre-image keys
](
../../specs/fault-proof.md#type-1-local-key
)
, the pre-image must be populated via
the
`FaultDisputeGame`
contract by calling the
`addLocalData`
function.
For
[
global keccak256 keys
](
../../specs/fault-proof.md#type-2-global-keccak256-key
)
, the data should be added directly
to the pre-image oracle contract.
## Resolving a Game
The final action required for a game is to resolve it by calling the
`resolve`
method in the
`FaultDisputeGame`
contract. This can only be done once the clock of the left-most uncontested claim’s parent has expired. A game can only
be resolved once.
There are no inputs required for the
`resolve`
method. When successful, a log event is emitted with the game’s final
status.
A helper script,
[
resolve.sh
](
../../op-challenger#resolvesh
)
, has been created to easily resolve a game and also
provides an example of using
`cast`
to manually call
`resolve`
and understand the result.
docs/fault-proof-alpha/run-challenger.md
0 → 100644
View file @
932a9bc9
## Running op-challenger
`op-challenger`
is a program that implements the honest actor algorithm to automatically “play” the dispute games.
### Prerequisites
-
The cannon pre-state downloaded from
[
Goerli deployment
](
./deployments.md#goerli
)
.
-
An account on the Goerli testnet with funds available. The amount of GöETH required depends on the number of claims
the challenger needs to post, but 0.01 ETH should be plenty to start.
-
A Goerli L1 node.
-
An archive node is not required.
-
Public RPC providers can be used, however a significant number of requests will need to be made which may exceed
rate limits for free plans.
-
An OP-Goerli L2 archive node with
`debug`
APIs enabled.
-
An archive node is required to ensure world-state pre-images remain available.
-
Public RPC providers are generally not usable as they don’t support the
`debug_dbGet`
RPC method.
-
Approximately 3.5Gb of disk space for each game being played.
### Starting op-challenger
In the top level of the monorepo, replace the placeholders and then run:
```
bash
# Build the required components
make op-challenger op-program cannon
# Run op-challenger
./op-challenger/bin/op-challenger
\
--trace-type
cannon
\
--l1-eth-rpc
<L1_URL>
\
--game-factory-address
<DISPUTE_GAME_FACTORY_ADDRESS>
\
--agree-with-proposed-output
=
true
\
--datadir
temp/challenger-goerli
\
--cannon-network
goerli
\
--cannon-bin
./cannon/bin/cannon
\
--cannon-server
./op-program/bin/op-program
\
--cannon-prestate
<PRESTATE>
\
--cannon-l2
<L2_URL>
\
--private-key
<PRIVATE_KEY>
```
The placeholders are:
-
`<L1_URL>`
the Goerli L1 JSON RPC endpoint
-
`<DISPUTE_GAME_FACTORY_ADDRESS>`
the address of the dispute game factory contract (see
the
[
Goerli deployment details
](
./deployments.md#goerli
)
)
-
`<PRESTATE>`
the prestate.json downloaded above. Note that this needs to precisely match the prestate used on-chain so
must be the downloaded version and not a version built locally (see the
[
Goerli deployment details
](
./deployments.md#goerli
)
)
-
`<L2_URL>`
the OP-Goerli L2 archive node JSON RPC endpoint
-
`<PRIVATE_KEY>`
the private key for a funded Goerli account. For other ways to specify the account to use
see
`./op-challenger/bin/op-challenger --help`
### Restricting Games to Play
By default
`op-challenger`
will generate traces and respond to any game created by the dispute game factory contract. On
a public testnet like Goerli, that could be a large number of games, requiring significant CPU and disk resources. To
avoid this,
`op-challenger`
supports specifying an allowlist of games for it to respond to with the
`--game-allowlist`
option.
```
bash
./op-challenger/bin/op-challenger
\
...
\
--game-allowlist
<GAME_ADDR> <GAME_ADDR> <GAME_ADDR>...
```
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment