Commit 26f8c82f authored by Andreas Bigger's avatar Andreas Bigger

Merge branch 'develop' into refcell/verifyscript

parents 245b9995 b9ca24ef
...@@ -1275,6 +1275,9 @@ workflows: ...@@ -1275,6 +1275,9 @@ workflows:
- go-lint: - go-lint:
name: op-proposer-lint name: op-proposer-lint
module: op-proposer module: op-proposer
- go-lint:
name: op-challenger-lint
module: op-challenger
- go-lint: - go-lint:
name: op-program-lint name: op-program-lint
module: op-program module: op-program
...@@ -1300,6 +1303,9 @@ workflows: ...@@ -1300,6 +1303,9 @@ workflows:
- go-test: - go-test:
name: op-proposer-tests name: op-proposer-tests
module: op-proposer module: op-proposer
- go-test:
name: op-challenger-tests
module: op-challenger
- go-test: - go-test:
name: op-program-tests name: op-program-tests
module: op-program module: op-program
...@@ -1322,6 +1328,7 @@ workflows: ...@@ -1322,6 +1328,7 @@ workflows:
- op-e2e-lint - op-e2e-lint
- op-node-lint - op-node-lint
- op-proposer-lint - op-proposer-lint
- op-challenger-lint
- op-program-lint - op-program-lint
- op-service-lint - op-service-lint
- op-batcher-tests - op-batcher-tests
...@@ -1329,6 +1336,7 @@ workflows: ...@@ -1329,6 +1336,7 @@ workflows:
- op-chain-ops-tests - op-chain-ops-tests
- op-node-tests - op-node-tests
- op-proposer-tests - op-proposer-tests
- op-challenger-tests
- op-program-tests - op-program-tests
- op-service-tests - op-service-tests
- op-e2e-WS-tests - op-e2e-WS-tests
...@@ -1389,6 +1397,20 @@ workflows: ...@@ -1389,6 +1397,20 @@ workflows:
context: context:
- oplabs-gcr - oplabs-gcr
platforms: "linux/amd64,linux/arm64" platforms: "linux/amd64,linux/arm64"
- docker-build:
name: op-challenger-docker-build
docker_file: op-challenger/Dockerfile
docker_name: op-challenger
docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
docker_context: .
- docker-publish:
name: op-challenger-docker-publish
docker_file: op-challenger/Dockerfile
docker_name: op-challenger
docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
context:
- oplabs-gcr
platforms: "linux/amd64,linux/arm64"
- docker-build: - docker-build:
name: op-heartbeat-docker-build name: op-heartbeat-docker-build
docker_file: op-heartbeat/Dockerfile docker_file: op-heartbeat/Dockerfile
...@@ -1431,6 +1453,7 @@ workflows: ...@@ -1431,6 +1453,7 @@ workflows:
- op-node-docker-build - op-node-docker-build
- op-batcher-docker-build - op-batcher-docker-build
- op-proposer-docker-build - op-proposer-docker-build
- op-challenger-docker-build
- hive-test: - hive-test:
name: hive-test-p2p name: hive-test-p2p
version: <<pipeline.git.revision>> version: <<pipeline.git.revision>>
...@@ -1439,6 +1462,7 @@ workflows: ...@@ -1439,6 +1462,7 @@ workflows:
- op-node-docker-build - op-node-docker-build
- op-batcher-docker-build - op-batcher-docker-build
- op-proposer-docker-build - op-proposer-docker-build
- op-challenger-docker-build
- hive-test: - hive-test:
name: hive-test-l1ops name: hive-test-l1ops
version: <<pipeline.git.revision>> version: <<pipeline.git.revision>>
...@@ -1447,6 +1471,7 @@ workflows: ...@@ -1447,6 +1471,7 @@ workflows:
- op-node-docker-build - op-node-docker-build
- op-batcher-docker-build - op-batcher-docker-build
- op-proposer-docker-build - op-proposer-docker-build
- op-challenger-docker-build
release: release:
jobs: jobs:
- hold: - hold:
...@@ -1504,6 +1529,22 @@ workflows: ...@@ -1504,6 +1529,22 @@ workflows:
- oplabs-gcr-release - oplabs-gcr-release
requires: requires:
- hold - hold
- docker-release:
name: op-challenger-docker-release
filters:
tags:
only: /^op-challenger\/v.*/
branches:
ignore: /.*/
docker_file: op-challenger/Dockerfile
docker_name: op-challenger
docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
docker_context: .
platforms: "linux/amd64,linux/arm64"
context:
- oplabs-gcr-release
requires:
- hold
- docker-build: - docker-build:
name: op-migrate-docker-release name: op-migrate-docker-release
filters: filters:
......
...@@ -40,6 +40,10 @@ op-proposer: ...@@ -40,6 +40,10 @@ op-proposer:
make -C ./op-proposer op-proposer make -C ./op-proposer op-proposer
.PHONY: op-proposer .PHONY: op-proposer
op-challenger:
make -C ./op-challenger op-challenger
.PHONY: op-challenger
op-program: op-program:
make -C ./op-program op-program make -C ./op-program op-program
.PHONY: op-program .PHONY: op-program
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
[Optimism](https://www.optimism.io/) is a project dedicated to scaling Ethereum's technology and expanding its ability to coordinate people from across the world to build effective decentralized economies and governance systems. The [Optimism Collective](https://app.optimism.io/announcement) builds open-source software for running L2 blockchains and aims to address key governance and economic challenges in the wider cryptocurrency ecosystem. Optimism operates on the principle of **impact=profit**, the idea that individuals who positively impact the Collective should be proportionally rewarded with profit. **Change the incentives and you change the world.** [Optimism](https://www.optimism.io/) is a project dedicated to scaling Ethereum's technology and expanding its ability to coordinate people from across the world to build effective decentralized economies and governance systems. The [Optimism Collective](https://app.optimism.io/announcement) builds open-source software for running L2 blockchains and aims to address key governance and economic challenges in the wider cryptocurrency ecosystem. Optimism operates on the principle of **impact=profit**, the idea that individuals who positively impact the Collective should be proportionally rewarded with profit. **Change the incentives and you change the world.**
In this repository, you'll find numerous core components of the OP Stack, the decentralized software stack maintained by the Optimism Collective that powers Optimism and forms the backbone of blockchains like [OP Mainnet](https://explorer.optimism.io/) and [Base](https://www.coinbase.com/blog/introducing-base). Designed to be "aggressively open source," the OP Stack encourages you to explore, modify, extend, and test the code as needed. Although not all elements of the OP Stack are contained here, many of its essential components can be found within this repository. By collaborating on free, open software and shared standards, the Optimism Collective aims to prevent siloed software development and rapidly accelerate the development of the Ethereum ecosystem. Come contribute, build the future, and redefine power, together. In this repository, you'll find numerous core components of the OP Stack, the decentralized software stack maintained by the Optimism Collective that powers Optimism and forms the backbone of blockchains like [OP Mainnet](https://explorer.optimism.io/) and [Base](https://base.org). Designed to be "aggressively open source," the OP Stack encourages you to explore, modify, extend, and test the code as needed. Although not all elements of the OP Stack are contained here, many of its essential components can be found within this repository. By collaborating on free, open software and shared standards, the Optimism Collective aims to prevent siloed software development and rapidly accelerate the development of the Ethereum ecosystem. Come contribute, build the future, and redefine power, together.
## Documentation ## Documentation
......
FROM --platform=$BUILDPLATFORM golang:1.19.0-alpine3.15 as builder
ARG VERSION=v0.0.0
RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash
# build op-challenger with the shared go.mod & go.sum files
COPY ./op-challenger /app/op-challenger
COPY ./op-bindings /app/op-bindings
COPY ./op-node /app/op-node
COPY ./op-service /app/op-service
COPY ./op-signer /app/op-signer
COPY ./go.mod /app/go.mod
COPY ./go.sum /app/go.sum
COPY ./.git /app/.git
WORKDIR /app/op-challenger
RUN go mod download
ARG TARGETOS TARGETARCH
RUN make op-challenger VERSION="$VERSION" GOOS=$TARGETOS GOARCH=$TARGETARCH
FROM alpine:3.15
COPY --from=builder /app/op-challenger/bin/op-challenger /usr/local/bin
CMD ["op-challenger"]
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)"
op-challenger:
env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/op-challenger ./cmd
clean:
rm bin/op-challenger
test:
go test -v ./...
lint:
golangci-lint run -E goimports,sqlclosecheck,bodyclose,asciicheck,misspell,errorlint -e "errors.As" -e "errors.Is"
.PHONY: \
clean \
op-challenger \
test \
lint
# op-challenger
The `op-challenger` 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
[dispute game specs](../specs/dispute-game.md).
## Quickstart
First, clone this repo. Then, run `make`, which will build all required targets.
Alternatively, run `make devnet` to bring up the [devnet](../ops-bedrock/devnet-up.sh)
which deploys the [mock dispute game contracts](./contracts) as well as an
`op-challenger` instance.
Alternatively, you can build the `op-challenger` binary locally using the pre-configured
[Makefile](./Makefile) target by running `make build`, and then running `./op-challenger --help`
to see a list of available options.
## Usage
`op-challenger` is configurable via command line flags and environment variables. The help menu
shows the available config options and can be accessed by running `./op-challenger --help`.
Note that there are many global options, but the most important ones are:
- `OP_CHALLENGER_L1_ETH_RPC`: An L1 Ethereum RPC URL
- `OP_CHALLENGER_ROLLUP_RPC`: A Rollup Node RPC URL
- `OP_CHALLENGER_L2OO_ADDRESS`: The L2OutputOracle Contract Address
- `OP_CHALLENGER_DGF_ADDRESS`: Dispute Game Factory Contract Address
Here is a reduced output from running `./op-challenger --help`:
```bash
NAME:
op-challenger - Modular Challenger Agent
USAGE:
main [global options] command [command options] [arguments...]
VERSION:
1.0.0
DESCRIPTION:
A modular op-stack challenge agent for output dispute games written in golang.
COMMANDS:
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--l1-eth-rpc value HTTP provider URL for L1. [$OP_CHALLENGER_L1_ETH_RPC]
--rollup-rpc value HTTP provider URL for the rollup node. [$OP_CHALLENGER_ROLLUP_RPC]
--l2oo-address value Address of the L2OutputOracle contract. [$OP_CHALLENGER_L2OO_ADDRESS]
--dgf-address value Address of the DisputeGameFactory contract. [$OP_CHALLENGER_DGF_ADDRESS]
...
--help, -h show help
--version, -v print the version
```
package main
import (
"os"
flags "github.com/ethereum-optimism/optimism/op-challenger/flags"
log "github.com/ethereum/go-ethereum/log"
cli "github.com/urfave/cli"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
)
const Version = "0.1.0"
func main() {
oplog.SetupDefaults()
app := cli.NewApp()
app.Flags = flags.Flags
app.Version = Version
app.Name = "op-challenger"
app.Usage = "Challenge invalid L2OutputOracle outputs"
app.Description = "A modular op-stack challenge agent for dispute games written in golang."
app.Action = func(ctx *cli.Context) error {
log.Debug("Challenger not implemented...")
return nil
}
err := app.Run(os.Args)
if err != nil {
log.Crit("Application failed", "message", err)
}
}
package flags
import (
"fmt"
"github.com/urfave/cli"
opservice "github.com/ethereum-optimism/optimism/op-service"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
oppprof "github.com/ethereum-optimism/optimism/op-service/pprof"
oprpc "github.com/ethereum-optimism/optimism/op-service/rpc"
txmgr "github.com/ethereum-optimism/optimism/op-service/txmgr"
)
const envVarPrefix = "OP_CHALLENGER"
var (
// Required Flags
L1EthRpcFlag = cli.StringFlag{
Name: "l1-eth-rpc",
Usage: "HTTP provider URL for L1.",
EnvVar: opservice.PrefixEnvVar(envVarPrefix, "L1_ETH_RPC"),
}
RollupRpcFlag = cli.StringFlag{
Name: "rollup-rpc",
Usage: "HTTP provider URL for the rollup node.",
EnvVar: opservice.PrefixEnvVar(envVarPrefix, "ROLLUP_RPC"),
}
L2OOAddressFlag = cli.StringFlag{
Name: "l2oo-address",
Usage: "Address of the L2OutputOracle contract.",
EnvVar: opservice.PrefixEnvVar(envVarPrefix, "L2OO_ADDRESS"),
}
DGFAddressFlag = cli.StringFlag{
Name: "dgf-address",
Usage: "Address of the DisputeGameFactory contract.",
EnvVar: opservice.PrefixEnvVar(envVarPrefix, "DGF_ADDRESS"),
}
)
// requiredFlags are checked by [CheckRequired]
var requiredFlags = []cli.Flag{
L1EthRpcFlag,
RollupRpcFlag,
L2OOAddressFlag,
DGFAddressFlag,
}
// optionalFlags is a list of unchecked cli flags
var optionalFlags = []cli.Flag{}
func init() {
optionalFlags = append(optionalFlags, oprpc.CLIFlags(envVarPrefix)...)
optionalFlags = append(optionalFlags, oplog.CLIFlags(envVarPrefix)...)
optionalFlags = append(optionalFlags, opmetrics.CLIFlags(envVarPrefix)...)
optionalFlags = append(optionalFlags, oppprof.CLIFlags(envVarPrefix)...)
optionalFlags = append(optionalFlags, txmgr.CLIFlags(envVarPrefix)...)
Flags = append(requiredFlags, optionalFlags...)
}
// Flags contains the list of configuration options available to the binary.
var Flags []cli.Flag
func CheckRequired(ctx *cli.Context) error {
for _, f := range requiredFlags {
if !ctx.GlobalIsSet(f.GetName()) {
return fmt.Errorf("flag %s is required", f.GetName())
}
}
return nil
}
...@@ -71,6 +71,8 @@ func testVerifyL2OutputRootEmptyBlock(t *testing.T, detached bool) { ...@@ -71,6 +71,8 @@ func testVerifyL2OutputRootEmptyBlock(t *testing.T, detached bool) {
// Avoids flaky test by avoiding reorgs at epoch 0 // Avoids flaky test by avoiding reorgs at epoch 0
t.Log("Wait for safe head to advance once for setup") t.Log("Wait for safe head to advance once for setup")
// Safe head doesn't exist at genesis. Wait for the first one before proceeding
require.NoError(t, waitForSafeHead(ctx, 1, rollupClient))
ss, err := l2Seq.BlockByNumber(ctx, big.NewInt(int64(rpc.SafeBlockNumber))) ss, err := l2Seq.BlockByNumber(ctx, big.NewInt(int64(rpc.SafeBlockNumber)))
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, waitForSafeHead(ctx, ss.NumberU64()+cfg.DeployConfig.SequencerWindowSize+1, rollupClient)) require.NoError(t, waitForSafeHead(ctx, ss.NumberU64()+cfg.DeployConfig.SequencerWindowSize+1, rollupClient))
......
...@@ -6,7 +6,9 @@ import ( ...@@ -6,7 +6,9 @@ import (
"github.com/hashicorp/golang-lru/v2/simplelru" "github.com/hashicorp/golang-lru/v2/simplelru"
) )
const blockCacheSize = 2_000 // blockCacheSize should be set large enough to handle the pipeline reset process of walking back from L2 head to find
// the L1 origin that is old enough to start buffering channel data from.
const blockCacheSize = 3_000
const nodeCacheSize = 100_000 const nodeCacheSize = 100_000
const codeCacheSize = 10_000 const codeCacheSize = 10_000
......
...@@ -43,8 +43,8 @@ func RunProgram(logger log.Logger, preimageOracle io.ReadWriter, preimageHinter ...@@ -43,8 +43,8 @@ func RunProgram(logger log.Logger, preimageOracle io.ReadWriter, preimageHinter
pClient := preimage.NewOracleClient(preimageOracle) pClient := preimage.NewOracleClient(preimageOracle)
hClient := preimage.NewHintWriter(preimageHinter) hClient := preimage.NewHintWriter(preimageHinter)
l1PreimageOracle := l1.NewPreimageOracle(pClient, hClient) l1PreimageOracle := l1.NewCachingOracle(l1.NewPreimageOracle(pClient, hClient))
l2PreimageOracle := l2.NewPreimageOracle(pClient, hClient) l2PreimageOracle := l2.NewCachingOracle(l2.NewPreimageOracle(pClient, hClient))
bootInfo := NewBootstrapClient(pClient).BootInfo() bootInfo := NewBootstrapClient(pClient).BootInfo()
logger.Info("Program Bootstrapped", "bootInfo", bootInfo) logger.Info("Program Bootstrapped", "bootInfo", bootInfo)
......
...@@ -78,6 +78,11 @@ func TestNetwork(t *testing.T) { ...@@ -78,6 +78,11 @@ func TestNetwork(t *testing.T) {
name := name name := name
expected := cfg expected := cfg
t.Run("Network_"+name, func(t *testing.T) { t.Run("Network_"+name, func(t *testing.T) {
// TODO(CLI-3936) Re-enable test for other networks once bedrock migration is complete
if name != "goerli" {
t.Skipf("Not requiring chain config for network %s", name)
return
}
args := replaceRequiredArg("--network", name) args := replaceRequiredArg("--network", name)
cfg := configForArgs(t, args) cfg := configForArgs(t, args)
require.Equal(t, expected, *cfg.Rollup) require.Equal(t, expected, *cfg.Rollup)
......
package l1
import (
"context"
"github.com/ethereum-optimism/optimism/op-node/client"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-node/sources"
cll1 "github.com/ethereum-optimism/optimism/op-program/client/l1"
"github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum-optimism/optimism/op-program/preimage"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
)
func NewFetchingOracle(ctx context.Context, logger log.Logger, cfg *config.Config) (cll1.Oracle, error) {
rpc, err := client.NewRPC(ctx, logger, cfg.L1URL)
if err != nil {
return nil, err
}
source, err := sources.NewL1Client(rpc, logger, nil, sources.L1ClientDefaultConfig(cfg.Rollup, cfg.L1TrustRPC, cfg.L1RPCKind))
if err != nil {
return nil, err
}
return NewFetchingL1Oracle(ctx, logger, source), nil
}
func NewSource(logger log.Logger, oracle preimage.Oracle, hint preimage.Hinter, l1Head common.Hash) derive.L1Fetcher {
l1Oracle := cll1.NewCachingOracle(cll1.NewPreimageOracle(oracle, hint))
return cll1.NewOracleL1Client(logger, l1Oracle, l1Head)
}
package l2
import (
"context"
"fmt"
cll2 "github.com/ethereum-optimism/optimism/op-program/client/l2"
"github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum-optimism/optimism/op-program/preimage"
"github.com/ethereum/go-ethereum/log"
)
func NewEngine(logger log.Logger, pre preimage.Oracle, hint preimage.Hinter, cfg *config.Config) (*cll2.OracleEngine, error) {
oracle := cll2.NewCachingOracle(cll2.NewPreimageOracle(pre, hint))
engineBackend, err := cll2.NewOracleBackedL2Chain(logger, oracle, cfg.L2ChainConfig, cfg.L2Head)
if err != nil {
return nil, fmt.Errorf("create l2 chain: %w", err)
}
return cll2.NewOracleEngine(cfg.Rollup, logger, engineBackend), nil
}
func NewFetchingOracle(ctx context.Context, logger log.Logger, cfg *config.Config) (cll2.Oracle, error) {
oracle, err := NewFetchingL2Oracle(ctx, logger, cfg.L2URL, cfg.L2Head)
if err != nil {
return nil, fmt.Errorf("connect l2 oracle: %w", err)
}
return oracle, nil
}
...@@ -121,7 +121,6 @@ services: ...@@ -121,7 +121,6 @@ services:
OP_BATCHER_L1_ETH_RPC: http://l1:8545 OP_BATCHER_L1_ETH_RPC: http://l1:8545
OP_BATCHER_L2_ETH_RPC: http://l2:8545 OP_BATCHER_L2_ETH_RPC: http://l2:8545
OP_BATCHER_ROLLUP_RPC: http://op-node:8545 OP_BATCHER_ROLLUP_RPC: http://op-node:8545
OFFLINE_GAS_ESTIMATION: false
OP_BATCHER_MAX_CHANNEL_DURATION: 1 OP_BATCHER_MAX_CHANNEL_DURATION: 1
OP_BATCHER_SUB_SAFETY_MARGIN: 4 # SWS is 15, ChannelTimeout is 40 OP_BATCHER_SUB_SAFETY_MARGIN: 4 # SWS is 15, ChannelTimeout is 40
OP_BATCHER_POLL_INTERVAL: 1s OP_BATCHER_POLL_INTERVAL: 1s
......
...@@ -266,7 +266,7 @@ func main() { ...@@ -266,7 +266,7 @@ func main() {
checkErr(err, "Error creating secure trie") checkErr(err, "Error creating secure trie")
// Put a "true" bool in the storage slot // Put a "true" bool in the storage slot
state.Update(hash.Bytes(), []byte{0x01}) state.UpdateStorage(common.Address{}, hash.Bytes(), []byte{0x01})
// Create a secure trie for the world state // Create a secure trie for the world state
world, err := trie.NewStateTrie( world, err := trie.NewStateTrie(
...@@ -283,7 +283,7 @@ func main() { ...@@ -283,7 +283,7 @@ func main() {
} }
writer := new(bytes.Buffer) writer := new(bytes.Buffer)
checkErr(account.EncodeRLP(writer), "Error encoding account") checkErr(account.EncodeRLP(writer), "Error encoding account")
world.Update(predeploys.L2ToL1MessagePasserAddr.Bytes(), writer.Bytes()) world.UpdateStorage(common.Address{}, predeploys.L2ToL1MessagePasserAddr.Bytes(), writer.Bytes())
// Get the proof // Get the proof
var proof proofList var proof proofList
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment