forked from ethereum-optimism/optimism
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #79 from ethstorage/po/op-challenger2-template
chore(MSFDG): op-challenger2 template
- Loading branch information
Showing
181 changed files
with
28,500 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
bin | ||
.fault-game-address |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
GITCOMMIT ?= $(shell git rev-parse HEAD) | ||
GITDATE ?= $(shell git show -s --format='%ct') | ||
VERSION ?= v0.0.0 | ||
|
||
LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT) | ||
LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) | ||
LDFLAGSSTRING +=-X main.Version=$(VERSION) | ||
LDFLAGS := -ldflags "$(LDFLAGSSTRING)" | ||
|
||
# Use the old Apple linker to workaround broken xcode - https://github.com/golang/go/issues/65169 | ||
ifeq ($(shell uname),Darwin) | ||
FUZZLDFLAGS := -ldflags=-extldflags=-Wl,-ld_classic | ||
endif | ||
|
||
op-challenger2: | ||
env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/op-challenger2 ./cmd | ||
|
||
fuzz: | ||
go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzKeccak ./game/keccak/matrix | ||
|
||
clean: | ||
rm bin/op-challenger2 | ||
|
||
test: | ||
go test -v ./... | ||
|
||
visualize: | ||
./scripts/visualize.sh | ||
|
||
.PHONY: \ | ||
op-challenger2 \ | ||
clean \ | ||
test \ | ||
visualize |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
# op-challenger2 | ||
|
||
The `op-challenger2` is a modular **op-stack** challenge agent written in | ||
golang for dispute games including, but not limited to,attestation games, | ||
fault games, and validity games. To learn more about dispute games, visit | ||
the [fault proof specs][proof-specs]. | ||
|
||
[proof-specs]: https://specs.optimism.io/experimental/fault-proof/index.html | ||
|
||
## Quickstart | ||
|
||
To build the `op-challenger2`, run `make` (which executes the `make build` | ||
[Makefile](./Makefile) target). To view a list of available commands and | ||
options, run `./bin/op-challenger2 --help`. | ||
|
||
## Usage | ||
|
||
`op-challenger2` is configurable via command line flags and environment | ||
variables. The help menu shows the available config options and can be | ||
accessed by running `./op-challenger2 --help`. | ||
|
||
### Running with Cannon on Local Devnet | ||
|
||
To run `op-challenger2` against the local devnet, first clean and run | ||
the devnet from the root of the repository. | ||
```shell | ||
make devnet-clean | ||
make devnet-up | ||
``` | ||
|
||
Then build the `op-challenger2` with `make op-challenger2`. | ||
|
||
Run the `op-challenger2` with: | ||
```shell | ||
DISPUTE_GAME_FACTORY=$(jq -r .DisputeGameFactoryProxy .devnet/addresses.json) | ||
./op-challenger2/bin/op-challenger2 \ | ||
--trace-type cannon \ | ||
--l1-eth-rpc http://localhost:8545 \ | ||
--rollup-rpc http://localhost:9546 \ | ||
--game-factory-address $DISPUTE_GAME_FACTORY \ | ||
--datadir temp/challenger-data \ | ||
--cannon-rollup-config .devnet/rollup.json \ | ||
--cannon-l2-genesis .devnet/genesis-l2.json \ | ||
--cannon-bin ./cannon/bin/cannon \ | ||
--cannon-server ./op-program/bin/op-program \ | ||
--cannon-prestate ./op-program/bin/prestate.json \ | ||
--l2-eth-rpc http://localhost:9545 \ | ||
--mnemonic "test test test test test test test test test test test junk" \ | ||
--hd-path "m/44'/60'/0'/0/8" \ | ||
--num-confirmations 1 | ||
``` | ||
|
||
The mnemonic and hd-path above is a prefunded address on the devnet. | ||
The challenger will monitor dispute games and respond to any invalid | ||
claims by posting the correct trace as the counter-claim. The commands | ||
below can then be used to create and interact with games. | ||
|
||
## Subcommands | ||
|
||
The `op-challenger2` has a few subcommands to interact with on-chain | ||
fault dispute games. The subcommands support game creation, performing | ||
game moves, and viewing fault dispute game data. They should not be | ||
used in production and are intended to provide convenient manual testing. | ||
|
||
### create-game | ||
|
||
```shell | ||
./bin/op-challenger2 create-game \ | ||
--l1-eth-rpc <L1_ETH_RPC> \ | ||
--game-address <GAME_FACTORY_ADDRESS> \ | ||
--output-root <OUTPUT_ROOT> \ | ||
--l2-block-num <L2_BLOCK_NUM> \ | ||
<SIGNER_ARGS> | ||
``` | ||
|
||
Starts a new fault dispute game that disputes the latest output proposal | ||
in the L2 output oracle. | ||
|
||
* `L1_ETH_RPC` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). | ||
* `GAME_FACTORY_ADDRESS` - the address of the dispute game factory contract on L1. | ||
* `OUTPUT_ROOT` a hex encoded 32 byte hash that is used as the proposed output root. | ||
* `L2_BLOCK_NUM` the L2 block number the proposed output root is from. | ||
* `SIGNER_ARGS` arguments to specify the key to sign transactions with (e.g `--private-key`) | ||
|
||
Optionally, you may specify the game type (aka "trace type") using the `--trace-type` | ||
flag, which is set to the cannon trace type by default. | ||
|
||
### move | ||
|
||
The `move` subcommand can be run with either the `--attack` or `--defend` flag, | ||
but not both. | ||
|
||
```shell | ||
./bin/op-challenger2 move \ | ||
--l1-eth-rpc <L1_ETH_RPC> \ | ||
--game-address <GAME_ADDRESS> \ | ||
--attack \ | ||
--parent-index <PARENT_INDEX> \ | ||
--claim <CLAIM> \ | ||
<SIGNER_ARGS> | ||
``` | ||
|
||
Performs a move to either attack or defend the latest claim in the specified game. | ||
|
||
* `L1_ETH_RPC` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). | ||
* `GAME_ADDRESS` - the address of the dispute game to perform the move in. | ||
* `(attack|defend)` - the type of move to make. | ||
* `attack` indicates that the state hash in your local cannon trace differs to the state | ||
hash included in the latest claim. | ||
* `defend` indicates that the state hash in your local cannon trace matches the state hash | ||
included in the latest claim. | ||
* `PARENT_INDEX` - the index of the parent claim that will be countered by this new claim. | ||
The special value of `latest` will counter the latest claim added to the game. | ||
* `CLAIM` - the state hash to include in the counter-claim you are posting. | ||
* `SIGNER_ARGS` arguments to specify the key to sign transactions with (e.g `--private-key`) | ||
|
||
### resolve-claim | ||
|
||
```shell | ||
./bin/op-challenger2 resolve-claim \ | ||
--l1-eth-rpc <L1_ETH_RPC> \ | ||
--game-address <GAME_ADDRESS> \ | ||
--claim <CLAIM_INDEX> \ | ||
<SIGNER_ARGS> | ||
``` | ||
|
||
Resolves a claim in a dispute game. Note that this will fail if the claim has already been resolved or if the claim is | ||
not yet resolvable. If the claim is resolved successfully, the result is printed. | ||
|
||
* `L1_ETH_RPC` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). | ||
* `GAME_ADDRESS` - the address of the dispute game to resolve. | ||
* `CLAIM_INDEX` - the index of the claim to resolve. | ||
* `SIGNER_ARGS` arguments to specify the key to sign transactions with (e.g `--private-key`). | ||
|
||
### resolve | ||
|
||
```shell | ||
./bin/op-challenger2 resolve \ | ||
--l1-eth-rpc <L1_ETH_RPC> \ | ||
--game-address <GAME_ADDRESS> \ | ||
<SIGNER_ARGS> | ||
``` | ||
|
||
Resolves a dispute game. Note that this will fail if the dispute game has already | ||
been resolved or if the clocks have not yet expired and further moves are possible. | ||
If the game is resolved successfully, the result is printed. | ||
|
||
* `L1_ETH_RPC` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). | ||
* `GAME_ADDRESS` - the address of the dispute game to resolve. | ||
* `SIGNER_ARGS` arguments to specify the key to sign transactions with (e.g `--private-key`). | ||
|
||
### list-games | ||
|
||
```shell | ||
./bin/op-challenger2 list-games \ | ||
--l1-eth-rpc <L1_ETH_RPC> \ | ||
--game-factory-address <GAME_FACTORY_ADDRESS> | ||
``` | ||
|
||
Prints the games created by the game factory along with their current status. | ||
|
||
* `L1_ETH_RPC` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). | ||
* `GAME_FACTORY_ADDRESS` - the address of the dispute game factory contract on L1. | ||
|
||
### list-claims | ||
|
||
```shell | ||
./bin/op-challenger2 list-games \ | ||
--l1-eth-rpc <L1_ETH_RPC> \ | ||
--game-address <GAME_ADDRESS> | ||
``` | ||
|
||
Prints the list of current claims in a dispute game. | ||
|
||
* `L1_ETH_RPC` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). | ||
* `GAME_ADDRESS` - the address of the dispute game to list the move in. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package op_challenger2 | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/ethereum-optimism/optimism/op-challenger2/metrics" | ||
"github.com/ethereum/go-ethereum/log" | ||
|
||
"github.com/ethereum-optimism/optimism/op-challenger2/config" | ||
"github.com/ethereum-optimism/optimism/op-challenger2/game" | ||
"github.com/ethereum-optimism/optimism/op-service/cliapp" | ||
) | ||
|
||
// Main is the programmatic entry-point for running op-challenger2 with a given configuration. | ||
func Main(ctx context.Context, logger log.Logger, cfg *config.Config, m metrics.Metricer) (cliapp.Lifecycle, error) { | ||
if err := cfg.Check(); err != nil { | ||
return nil, err | ||
} | ||
return game.NewService(ctx, logger, cfg, m) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package op_challenger2 | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/ethereum-optimism/optimism/op-challenger2/config" | ||
"github.com/ethereum-optimism/optimism/op-challenger2/metrics" | ||
"github.com/ethereum-optimism/optimism/op-service/testlog" | ||
"github.com/ethereum/go-ethereum/log" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestMainShouldReturnErrorWhenConfigInvalid(t *testing.T) { | ||
cfg := &config.Config{} | ||
app, err := Main(context.Background(), testlog.Logger(t, log.LevelInfo), cfg, metrics.NoopMetrics) | ||
require.ErrorIs(t, err, cfg.Check()) | ||
require.Nil(t, app) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/ethereum-optimism/optimism/op-challenger2/config" | ||
"github.com/ethereum-optimism/optimism/op-challenger2/flags" | ||
"github.com/ethereum-optimism/optimism/op-challenger2/game/fault/contracts" | ||
contractMetrics "github.com/ethereum-optimism/optimism/op-challenger2/game/fault/contracts/metrics" | ||
"github.com/ethereum-optimism/optimism/op-challenger2/tools" | ||
opservice "github.com/ethereum-optimism/optimism/op-service" | ||
oplog "github.com/ethereum-optimism/optimism/op-service/log" | ||
"github.com/ethereum-optimism/optimism/op-service/sources/batching" | ||
"github.com/ethereum-optimism/optimism/op-service/txmgr" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/urfave/cli/v2" | ||
) | ||
|
||
var ( | ||
TraceTypeFlag = &cli.StringFlag{ | ||
Name: "trace-type", | ||
Usage: "Trace types to support.", | ||
EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "TRACE_TYPE"), | ||
Value: config.TraceTypeCannon.String(), | ||
} | ||
OutputRootFlag = &cli.StringFlag{ | ||
Name: "output-root", | ||
Usage: "The output root for the fault dispute game.", | ||
EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "OUTPUT_ROOT"), | ||
} | ||
L2BlockNumFlag = &cli.StringFlag{ | ||
Name: "l2-block-num", | ||
Usage: "The l2 block number for the game.", | ||
EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "L2_BLOCK_NUM"), | ||
} | ||
) | ||
|
||
func CreateGame(ctx *cli.Context) error { | ||
outputRoot := common.HexToHash(ctx.String(OutputRootFlag.Name)) | ||
traceType := ctx.Uint64(TraceTypeFlag.Name) | ||
l2BlockNum := ctx.Uint64(L2BlockNumFlag.Name) | ||
|
||
contract, txMgr, err := NewContractWithTxMgr[*contracts.DisputeGameFactoryContract](ctx, flags.FactoryAddressFlag.Name, | ||
func(ctx context.Context, metricer contractMetrics.ContractMetricer, address common.Address, caller *batching.MultiCaller) (*contracts.DisputeGameFactoryContract, error) { | ||
return contracts.NewDisputeGameFactoryContract(metricer, address, caller), nil | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("failed to create dispute game factory bindings: %w", err) | ||
} | ||
|
||
creator := tools.NewGameCreator(contract, txMgr) | ||
gameAddr, err := creator.CreateGame(ctx.Context, outputRoot, traceType, l2BlockNum) | ||
if err != nil { | ||
return fmt.Errorf("failed to create game: %w", err) | ||
} | ||
fmt.Printf("Fetched Game Address: %s\n", gameAddr.String()) | ||
return nil | ||
} | ||
|
||
func createGameFlags() []cli.Flag { | ||
cliFlags := []cli.Flag{ | ||
flags.L1EthRpcFlag, | ||
flags.FactoryAddressFlag, | ||
TraceTypeFlag, | ||
OutputRootFlag, | ||
L2BlockNumFlag, | ||
} | ||
cliFlags = append(cliFlags, txmgr.CLIFlagsWithDefaults(flags.EnvVarPrefix, txmgr.DefaultChallengerFlagValues)...) | ||
cliFlags = append(cliFlags, oplog.CLIFlags(flags.EnvVarPrefix)...) | ||
return cliFlags | ||
} | ||
|
||
var CreateGameCommand = &cli.Command{ | ||
Name: "create-game", | ||
Usage: "Creates a dispute game via the factory", | ||
Description: "Creates a dispute game via the factory", | ||
Action: CreateGame, | ||
Flags: createGameFlags(), | ||
} |
Oops, something went wrong.