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
a382b9e2
Unverified
Commit
a382b9e2
authored
Aug 23, 2023
by
mergify[bot]
Committed by
GitHub
Aug 23, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into indexer.sql.constraints
parents
a9ef72e1
d7ac3e97
Changes
60
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
60 changed files
with
1098 additions
and
723 deletions
+1098
-723
CONTRIBUTING.md
CONTRIBUTING.md
+9
-9
Makefile
Makefile
+3
-3
__init__.py
bedrock-devnet/devnet/__init__.py
+4
-4
Dockerfile
endpoint-monitor/Dockerfile
+2
-2
go.mod
go.mod
+1
-1
Dockerfile
indexer/Dockerfile
+2
-2
README.md
indexer/README.md
+1
-1
README.md
indexer/ui/README.md
+1
-1
Dockerfile
op-batcher/Dockerfile
+2
-2
shadow_compressor_test.go
op-batcher/compressor/shadow_compressor_test.go
+1
-1
memory_db_test.go
op-chain-ops/state/memory_db_test.go
+3
-1
Dockerfile
op-challenger/Dockerfile
+2
-2
main_test.go
op-challenger/cmd/main_test.go
+29
-11
config.go
op-challenger/config/config.go
+19
-6
config_test.go
op-challenger/config/config_test.go
+6
-7
abi_test.go
op-challenger/fault/abi_test.go
+3
-3
agent.go
op-challenger/fault/agent.go
+19
-2
agent_test.go
op-challenger/fault/agent_test.go
+31
-0
caller.go
op-challenger/fault/caller.go
+1
-2
executor_test.go
op-challenger/fault/cannon/executor_test.go
+1
-2
provider.go
op-challenger/fault/cannon/provider.go
+3
-4
provider_test.go
op-challenger/fault/cannon/provider_test.go
+0
-16
disk.go
op-challenger/fault/disk.go
+57
-0
disk_test.go
op-challenger/fault/disk_test.go
+57
-0
factory.go
op-challenger/fault/factory.go
+11
-6
factory_test.go
op-challenger/fault/factory_test.go
+11
-8
monitor.go
op-challenger/fault/monitor.go
+57
-6
monitor_test.go
op-challenger/fault/monitor_test.go
+139
-11
player.go
op-challenger/fault/player.go
+14
-4
player_test.go
op-challenger/fault/player_test.go
+42
-28
responder.go
op-challenger/fault/responder.go
+13
-6
responder_test.go
op-challenger/fault/responder_test.go
+135
-137
service.go
op-challenger/fault/service.go
+12
-3
types.go
op-challenger/fault/types/types.go
+9
-0
types_test.go
op-challenger/fault/types/types_test.go
+23
-0
flags.go
op-challenger/flags/flags.go
+15
-10
charlie.sh
op-challenger/scripts/alphabet/charlie.sh
+8
-1
mallory.sh
op-challenger/scripts/alphabet/mallory.sh
+8
-1
helper.go
op-e2e/e2eutils/challenger/helper.go
+35
-9
cannon_helper.go
op-e2e/e2eutils/disputegame/cannon_helper.go
+3
-1
game_helper.go
op-e2e/e2eutils/disputegame/game_helper.go
+4
-0
helper.go
op-e2e/e2eutils/disputegame/helper.go
+1
-1
faultproof_test.go
op-e2e/faultproof_test.go
+7
-3
Dockerfile
op-exporter/Dockerfile
+2
-2
go.mod
op-exporter/go.mod
+1
-1
Dockerfile
op-heartbeat/Dockerfile
+2
-2
Dockerfile
op-node/Dockerfile
+2
-2
l1_block_info_test.go
op-node/rollup/derive/l1_block_info_test.go
+2
-1
eth_client_test.go
op-node/sources/eth_client_test.go
+2
-2
Dockerfile
op-program/Dockerfile
+2
-2
Dockerfile
op-proposer/Dockerfile
+2
-2
Dockerfile
op-wheel/Dockerfile
+2
-2
package.json
package.json
+3
-3
package.json
packages/contracts-bedrock/package.json
+1
-1
go.mod
packages/contracts-bedrock/test-case-generator/go.mod
+1
-1
package.json
packages/contracts-ts/package.json
+1
-1
package.json
packages/fee-estimation/package.json
+1
-1
pnpm-lock.yaml
pnpm-lock.yaml
+267
-380
go.mod
proxyd/go.mod
+1
-1
devnet.md
specs/meta/devnet.md
+2
-2
No files found.
CONTRIBUTING.md
View file @
a382b9e2
...
@@ -119,7 +119,7 @@ Note that these environment variables significantly speed up build time.
...
@@ -119,7 +119,7 @@ Note that these environment variables significantly speed up build time.
cd
ops-bedrock
cd
ops-bedrock
export
COMPOSE_DOCKER_CLI_BUILD
=
1
export
COMPOSE_DOCKER_CLI_BUILD
=
1
export
DOCKER_BUILDKIT
=
1
export
DOCKER_BUILDKIT
=
1
docker
-
compose build
docker
compose build
```
```
Source code changes can have an impact on more than one container.
Source code changes can have an impact on more than one container.
...
@@ -127,9 +127,9 @@ Source code changes can have an impact on more than one container.
...
@@ -127,9 +127,9 @@ Source code changes can have an impact on more than one container.
```
bash
```
bash
cd
ops-bedrock
cd
ops-bedrock
docker
-
compose down
docker
compose down
docker
-
compose build
docker
compose build
docker
-
compose up
docker
compose up
```
```
**If a node process exits with exit code: 137**
you may need to increase the default memory limit of docker containers
**If a node process exits with exit code: 137**
you may need to increase the default memory limit of docker containers
...
@@ -141,18 +141,18 @@ cd optimism
...
@@ -141,18 +141,18 @@ cd optimism
pnpm clean
pnpm clean
pnpm build
pnpm build
cd
ops
cd
ops
docker
-
compose down
-v
docker
compose down
-v
docker
-
compose build
docker
compose build
docker
-
compose up
docker
compose up
```
```
#### Viewing docker container logs
#### Viewing docker container logs
By default, the
`docker
-
compose up`
command will show logs from all services, and that
By default, the
`docker
compose up`
command will show logs from all services, and that
can be hard to filter through. In order to view the logs from a specific service, you can run:
can be hard to filter through. In order to view the logs from a specific service, you can run:
```
bash
```
bash
docker
-
compose logs
--follow
<service name>
docker
compose logs
--follow
<service name>
```
```
### Running tests
### Running tests
...
...
Makefile
View file @
a382b9e2
...
@@ -101,13 +101,13 @@ devnet-test:
...
@@ -101,13 +101,13 @@ devnet-test:
.PHONY
:
devnet-test
.PHONY
:
devnet-test
devnet-down
:
devnet-down
:
@
(
cd
./ops-bedrock
&&
GENESIS_TIMESTAMP
=
$(
shell
date
+%s
)
docker
-
compose stop
)
@
(
cd
./ops-bedrock
&&
GENESIS_TIMESTAMP
=
$(
shell
date
+%s
)
docker
compose stop
)
.PHONY
:
devnet-down
.PHONY
:
devnet-down
devnet-clean
:
devnet-clean
:
rm
-rf
./packages/contracts-bedrock/deployments/devnetL1
rm
-rf
./packages/contracts-bedrock/deployments/devnetL1
rm
-rf
./.devnet
rm
-rf
./.devnet
cd
./ops-bedrock
&&
docker
-
compose down
cd
./ops-bedrock
&&
docker
compose down
docker image
ls
'ops-bedrock*'
--format
=
'{{.Repository}}'
| xargs
-r
docker rmi
docker image
ls
'ops-bedrock*'
--format
=
'{{.Repository}}'
| xargs
-r
docker rmi
docker volume
ls
--filter
name
=
ops-bedrock
--format
=
'{{.Name}}'
| xargs
-r
docker volume
rm
docker volume
ls
--filter
name
=
ops-bedrock
--format
=
'{{.Name}}'
| xargs
-r
docker volume
rm
.PHONY
:
devnet-clean
.PHONY
:
devnet-clean
...
@@ -116,7 +116,7 @@ devnet-allocs:
...
@@ -116,7 +116,7 @@ devnet-allocs:
PYTHONPATH
=
./bedrock-devnet python3 ./bedrock-devnet/main.py
--monorepo-dir
=
.
--allocs
PYTHONPATH
=
./bedrock-devnet python3 ./bedrock-devnet/main.py
--monorepo-dir
=
.
--allocs
devnet-logs
:
devnet-logs
:
@
(
cd
./ops-bedrock
&&
docker
-
compose logs
-f
)
@
(
cd
./ops-bedrock
&&
docker
compose logs
-f
)
.PHONY: devnet-logs
.PHONY: devnet-logs
test-unit
:
test-unit
:
...
...
bedrock-devnet/devnet/__init__.py
View file @
a382b9e2
...
@@ -93,7 +93,7 @@ def main():
...
@@ -93,7 +93,7 @@ def main():
return
return
log
.
info
(
'Building docker images'
)
log
.
info
(
'Building docker images'
)
run_command
([
'docker
-
compose'
,
'build'
,
'--progress'
,
'plain'
],
cwd
=
paths
.
ops_bedrock_dir
,
env
=
{
run_command
([
'docker
'
,
'
compose'
,
'build'
,
'--progress'
,
'plain'
],
cwd
=
paths
.
ops_bedrock_dir
,
env
=
{
'PWD'
:
paths
.
ops_bedrock_dir
'PWD'
:
paths
.
ops_bedrock_dir
})
})
...
@@ -173,7 +173,7 @@ def devnet_deploy(paths):
...
@@ -173,7 +173,7 @@ def devnet_deploy(paths):
],
cwd
=
paths
.
op_node_dir
)
],
cwd
=
paths
.
op_node_dir
)
log
.
info
(
'Starting L1.'
)
log
.
info
(
'Starting L1.'
)
run_command
([
'docker
-
compose'
,
'up'
,
'-d'
,
'l1'
],
cwd
=
paths
.
ops_bedrock_dir
,
env
=
{
run_command
([
'docker
'
,
'
compose'
,
'up'
,
'-d'
,
'l1'
],
cwd
=
paths
.
ops_bedrock_dir
,
env
=
{
'PWD'
:
paths
.
ops_bedrock_dir
'PWD'
:
paths
.
ops_bedrock_dir
})
})
wait_up
(
8545
)
wait_up
(
8545
)
...
@@ -196,7 +196,7 @@ def devnet_deploy(paths):
...
@@ -196,7 +196,7 @@ def devnet_deploy(paths):
addresses
=
read_json
(
paths
.
addresses_json_path
)
addresses
=
read_json
(
paths
.
addresses_json_path
)
log
.
info
(
'Bringing up L2.'
)
log
.
info
(
'Bringing up L2.'
)
run_command
([
'docker
-
compose'
,
'up'
,
'-d'
,
'l2'
],
cwd
=
paths
.
ops_bedrock_dir
,
env
=
{
run_command
([
'docker
'
,
'
compose'
,
'up'
,
'-d'
,
'l2'
],
cwd
=
paths
.
ops_bedrock_dir
,
env
=
{
'PWD'
:
paths
.
ops_bedrock_dir
'PWD'
:
paths
.
ops_bedrock_dir
})
})
wait_up
(
9545
)
wait_up
(
9545
)
...
@@ -208,7 +208,7 @@ def devnet_deploy(paths):
...
@@ -208,7 +208,7 @@ def devnet_deploy(paths):
log
.
info
(
f
'Using batch inbox {batch_inbox_address}'
)
log
.
info
(
f
'Using batch inbox {batch_inbox_address}'
)
log
.
info
(
'Bringing up everything else.'
)
log
.
info
(
'Bringing up everything else.'
)
run_command
([
'docker
-
compose'
,
'up'
,
'-d'
,
'op-node'
,
'op-proposer'
,
'op-batcher'
],
cwd
=
paths
.
ops_bedrock_dir
,
env
=
{
run_command
([
'docker
'
,
'
compose'
,
'up'
,
'-d'
,
'op-node'
,
'op-proposer'
,
'op-batcher'
],
cwd
=
paths
.
ops_bedrock_dir
,
env
=
{
'PWD'
:
paths
.
ops_bedrock_dir
,
'PWD'
:
paths
.
ops_bedrock_dir
,
'L2OO_ADDRESS'
:
l2_output_oracle
,
'L2OO_ADDRESS'
:
l2_output_oracle
,
'SEQUENCER_BATCH_INBOX_ADDRESS'
:
batch_inbox_address
'SEQUENCER_BATCH_INBOX_ADDRESS'
:
batch_inbox_address
...
...
endpoint-monitor/Dockerfile
View file @
a382b9e2
FROM
golang:1.
19.9-alpine3.16
as builder
FROM
golang:1.
20.7-alpine3.18
as builder
RUN
apk
--no-cache
add make jq bash git alpine-sdk
RUN
apk
--no-cache
add make jq bash git alpine-sdk
...
@@ -16,7 +16,7 @@ RUN go mod download
...
@@ -16,7 +16,7 @@ RUN go mod download
RUN
make build
RUN
make build
FROM
alpine:3.1
6
FROM
alpine:3.1
8
RUN
apk
--no-cache
add ca-certificates
RUN
apk
--no-cache
add ca-certificates
RUN
addgroup
-S
app
&&
adduser
-S
app
-G
app
RUN
addgroup
-S
app
&&
adduser
-S
app
-G
app
...
...
go.mod
View file @
a382b9e2
module github.com/ethereum-optimism/optimism
module github.com/ethereum-optimism/optimism
go 1.
19
go 1.
20
require (
require (
github.com/BurntSushi/toml v1.3.2
github.com/BurntSushi/toml v1.3.2
...
...
indexer/Dockerfile
View file @
a382b9e2
FROM
--platform=$BUILDPLATFORM golang:1.
19.9-alpine3.16
as builder
FROM
--platform=$BUILDPLATFORM golang:1.
20.7-alpine3.18
as builder
RUN
apk add
--no-cache
make gcc musl-dev linux-headers git jq bash
RUN
apk add
--no-cache
make gcc musl-dev linux-headers git jq bash
...
@@ -18,7 +18,7 @@ RUN go mod download
...
@@ -18,7 +18,7 @@ RUN go mod download
RUN
make indexer
RUN
make indexer
FROM
alpine:3.1
6
FROM
alpine:3.1
8
COPY
--from=builder /app/indexer/indexer /usr/local/bin
COPY
--from=builder /app/indexer/indexer /usr/local/bin
...
...
indexer/README.md
View file @
a382b9e2
...
@@ -16,7 +16,7 @@ All tests can be ran by running `make test` from the `/indexer` directory. This
...
@@ -16,7 +16,7 @@ All tests can be ran by running `make test` from the `/indexer` directory. This
-
install docker
-
install docker
-
`cp example.env .env`
-
`cp example.env .env`
-
fill in .env
-
fill in .env
-
run
`docker
-
compose up`
to start the indexer vs optimism goerli network
-
run
`docker
compose up`
to start the indexer vs optimism goerli network
### Run indexer with go
### Run indexer with go
...
...
indexer/ui/README.md
View file @
a382b9e2
...
@@ -7,7 +7,7 @@ A simple UI for exploring the indexer DB using [Prisma studio](https://www.prism
...
@@ -7,7 +7,7 @@ A simple UI for exploring the indexer DB using [Prisma studio](https://www.prism
Included in the docker-compose file as
`ui`
service
Included in the docker-compose file as
`ui`
service
```
bash
```
bash
docker
-
compose up
docker
compose up
```
```
Prisma can be viewed at
[
localhost:5555
](
http://localhost:5555
)
Prisma can be viewed at
[
localhost:5555
](
http://localhost:5555
)
...
...
op-batcher/Dockerfile
View file @
a382b9e2
FROM
--platform=$BUILDPLATFORM golang:1.
19.9-alpine3.16
as builder
FROM
--platform=$BUILDPLATFORM golang:1.
20.7-alpine3.18
as builder
ARG
VERSION=v0.0.0
ARG
VERSION=v0.0.0
...
@@ -23,7 +23,7 @@ ARG TARGETOS TARGETARCH
...
@@ -23,7 +23,7 @@ ARG TARGETOS TARGETARCH
RUN
make op-batcher
VERSION
=
"
$VERSION
"
GOOS
=
$TARGETOS
GOARCH
=
$TARGETARCH
RUN
make op-batcher
VERSION
=
"
$VERSION
"
GOOS
=
$TARGETOS
GOARCH
=
$TARGETARCH
FROM
alpine:3.1
6
FROM
alpine:3.1
8
COPY
--from=builder /app/op-batcher/bin/op-batcher /usr/local/bin
COPY
--from=builder /app/op-batcher/bin/op-batcher /usr/local/bin
...
...
op-batcher/compressor/shadow_compressor_test.go
View file @
a382b9e2
...
@@ -3,8 +3,8 @@ package compressor_test
...
@@ -3,8 +3,8 @@ package compressor_test
import
(
import
(
"bytes"
"bytes"
"compress/zlib"
"compress/zlib"
"crypto/rand"
"io"
"io"
"math/rand"
"testing"
"testing"
"github.com/ethereum-optimism/optimism/op-batcher/compressor"
"github.com/ethereum-optimism/optimism/op-batcher/compressor"
...
...
op-chain-ops/state/memory_db_test.go
View file @
a382b9e2
package
state_test
package
state_test
import
(
import
(
crand
"crypto/rand"
"math/big"
"math/big"
"math/rand"
"math/rand"
"testing"
"testing"
...
@@ -47,7 +48,8 @@ func TestCode(t *testing.T) {
...
@@ -47,7 +48,8 @@ func TestCode(t *testing.T) {
require
.
Nil
(
t
,
pre
)
require
.
Nil
(
t
,
pre
)
code
:=
make
([]
byte
,
rand
.
Intn
(
1024
))
code
:=
make
([]
byte
,
rand
.
Intn
(
1024
))
rand
.
Read
(
code
)
_
,
err
:=
crand
.
Read
(
code
)
require
.
NoError
(
t
,
err
)
db
.
SetCode
(
addr
,
code
)
db
.
SetCode
(
addr
,
code
)
...
...
op-challenger/Dockerfile
View file @
a382b9e2
FROM
--platform=$BUILDPLATFORM golang:1.
19.0-alpine3.15
as builder
FROM
--platform=$BUILDPLATFORM golang:1.
20.7-alpine3.18
as builder
ARG
VERSION=v0.0.0
ARG
VERSION=v0.0.0
...
@@ -27,7 +27,7 @@ ARG TARGETOS TARGETARCH
...
@@ -27,7 +27,7 @@ ARG TARGETOS TARGETARCH
RUN
make op-challenger
VERSION
=
"
$VERSION
"
GOOS
=
$TARGETOS
GOARCH
=
$TARGETARCH
RUN
make op-challenger
VERSION
=
"
$VERSION
"
GOOS
=
$TARGETOS
GOARCH
=
$TARGETARCH
FROM
alpine:3.1
5
FROM
alpine:3.1
8
COPY
--from=builder /app/op-challenger/bin/op-challenger /usr/local/bin
COPY
--from=builder /app/op-challenger/bin/op-challenger /usr/local/bin
...
...
op-challenger/cmd/main_test.go
View file @
a382b9e2
...
@@ -4,6 +4,7 @@ import (
...
@@ -4,6 +4,7 @@ import (
"context"
"context"
"fmt"
"fmt"
"testing"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
...
@@ -21,7 +22,7 @@ var (
...
@@ -21,7 +22,7 @@ var (
cannonBin
=
"./bin/cannon"
cannonBin
=
"./bin/cannon"
cannonServer
=
"./bin/op-program"
cannonServer
=
"./bin/op-program"
cannonPreState
=
"./pre.json"
cannonPreState
=
"./pre.json"
cannonDatadir
=
"./test_data"
datadir
=
"./test_data"
cannonL2
=
"http://example.com:9545"
cannonL2
=
"http://example.com:9545"
alphabetTrace
=
"abcdefghijz"
alphabetTrace
=
"abcdefghijz"
agreeWithProposedOutput
=
"true"
agreeWithProposedOutput
=
"true"
...
@@ -44,14 +45,14 @@ func TestLogLevel(t *testing.T) {
...
@@ -44,14 +45,14 @@ func TestLogLevel(t *testing.T) {
func
TestDefaultCLIOptionsMatchDefaultConfig
(
t
*
testing
.
T
)
{
func
TestDefaultCLIOptionsMatchDefaultConfig
(
t
*
testing
.
T
)
{
cfg
:=
configForArgs
(
t
,
addRequiredArgs
(
config
.
TraceTypeAlphabet
))
cfg
:=
configForArgs
(
t
,
addRequiredArgs
(
config
.
TraceTypeAlphabet
))
defaultCfg
:=
config
.
NewConfig
(
common
.
HexToAddress
(
gameFactoryAddressValue
),
l1EthRpc
,
config
.
TraceTypeAlphabet
,
true
)
defaultCfg
:=
config
.
NewConfig
(
common
.
HexToAddress
(
gameFactoryAddressValue
),
l1EthRpc
,
config
.
TraceTypeAlphabet
,
true
,
datadir
)
// Add in the extra CLI options required when using alphabet trace type
// Add in the extra CLI options required when using alphabet trace type
defaultCfg
.
AlphabetTrace
=
alphabetTrace
defaultCfg
.
AlphabetTrace
=
alphabetTrace
require
.
Equal
(
t
,
defaultCfg
,
cfg
)
require
.
Equal
(
t
,
defaultCfg
,
cfg
)
}
}
func
TestDefaultConfigIsValid
(
t
*
testing
.
T
)
{
func
TestDefaultConfigIsValid
(
t
*
testing
.
T
)
{
cfg
:=
config
.
NewConfig
(
common
.
HexToAddress
(
gameFactoryAddressValue
),
l1EthRpc
,
config
.
TraceTypeAlphabet
,
true
)
cfg
:=
config
.
NewConfig
(
common
.
HexToAddress
(
gameFactoryAddressValue
),
l1EthRpc
,
config
.
TraceTypeAlphabet
,
true
,
datadir
)
// Add in options that are required based on the specific trace type
// Add in options that are required based on the specific trace type
// To avoid needing to specify unused options, these aren't included in the params for NewConfig
// To avoid needing to specify unused options, these aren't included in the params for NewConfig
cfg
.
AlphabetTrace
=
alphabetTrace
cfg
.
AlphabetTrace
=
alphabetTrace
...
@@ -191,18 +192,18 @@ func TestCannonAbsolutePrestate(t *testing.T) {
...
@@ -191,18 +192,18 @@ func TestCannonAbsolutePrestate(t *testing.T) {
})
})
}
}
func
Test
Cannon
DataDir
(
t
*
testing
.
T
)
{
func
TestDataDir
(
t
*
testing
.
T
)
{
t
.
Run
(
"
Not
RequiredForAlphabetTrace"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"RequiredForAlphabetTrace"
,
func
(
t
*
testing
.
T
)
{
configForArgs
(
t
,
addRequiredArgsExcept
(
config
.
TraceTypeAlphabet
,
"--cannon
-datadir"
))
verifyArgsInvalid
(
t
,
"flag datadir is required"
,
addRequiredArgsExcept
(
config
.
TraceTypeAlphabet
,
"-
-datadir"
))
})
})
t
.
Run
(
"Required"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"Required
ForCannonTrace
"
,
func
(
t
*
testing
.
T
)
{
verifyArgsInvalid
(
t
,
"flag
cannon-datadir is required"
,
addRequiredArgsExcept
(
config
.
TraceTypeCannon
,
"--cannon
-datadir"
))
verifyArgsInvalid
(
t
,
"flag
datadir is required"
,
addRequiredArgsExcept
(
config
.
TraceTypeCannon
,
"-
-datadir"
))
})
})
t
.
Run
(
"Valid"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"Valid"
,
func
(
t
*
testing
.
T
)
{
cfg
:=
configForArgs
(
t
,
addRequiredArgsExcept
(
config
.
TraceTypeCannon
,
"--
cannon-datadir"
,
"--cannon
-datadir=/foo/bar/cannon"
))
cfg
:=
configForArgs
(
t
,
addRequiredArgsExcept
(
config
.
TraceTypeCannon
,
"--
datadir"
,
"-
-datadir=/foo/bar/cannon"
))
require
.
Equal
(
t
,
"/foo/bar/cannon"
,
cfg
.
Cannon
Datadir
)
require
.
Equal
(
t
,
"/foo/bar/cannon"
,
cfg
.
Datadir
)
})
})
}
}
...
@@ -233,6 +234,23 @@ func TestCannonSnapshotFreq(t *testing.T) {
...
@@ -233,6 +234,23 @@ func TestCannonSnapshotFreq(t *testing.T) {
})
})
}
}
func
TestGameWindow
(
t
*
testing
.
T
)
{
t
.
Run
(
"UsesDefault"
,
func
(
t
*
testing
.
T
)
{
cfg
:=
configForArgs
(
t
,
addRequiredArgs
(
config
.
TraceTypeAlphabet
))
require
.
Equal
(
t
,
config
.
DefaultGameWindow
,
cfg
.
GameWindow
)
})
t
.
Run
(
"Valid"
,
func
(
t
*
testing
.
T
)
{
cfg
:=
configForArgs
(
t
,
addRequiredArgs
(
config
.
TraceTypeAlphabet
,
"--game-window=1m"
))
require
.
Equal
(
t
,
time
.
Duration
(
time
.
Minute
),
cfg
.
GameWindow
)
})
t
.
Run
(
"ParsesDefault"
,
func
(
t
*
testing
.
T
)
{
cfg
:=
configForArgs
(
t
,
addRequiredArgs
(
config
.
TraceTypeAlphabet
,
"--game-window=264h"
))
require
.
Equal
(
t
,
config
.
DefaultGameWindow
,
cfg
.
GameWindow
)
})
}
func
TestRequireEitherCannonNetworkOrRollupAndGenesis
(
t
*
testing
.
T
)
{
func
TestRequireEitherCannonNetworkOrRollupAndGenesis
(
t
*
testing
.
T
)
{
verifyArgsInvalid
(
verifyArgsInvalid
(
t
,
t
,
...
@@ -335,6 +353,7 @@ func requiredArgs(traceType config.TraceType) map[string]string {
...
@@ -335,6 +353,7 @@ func requiredArgs(traceType config.TraceType) map[string]string {
"--l1-eth-rpc"
:
l1EthRpc
,
"--l1-eth-rpc"
:
l1EthRpc
,
"--game-factory-address"
:
gameFactoryAddressValue
,
"--game-factory-address"
:
gameFactoryAddressValue
,
"--trace-type"
:
traceType
.
String
(),
"--trace-type"
:
traceType
.
String
(),
"--datadir"
:
datadir
,
}
}
switch
traceType
{
switch
traceType
{
case
config
.
TraceTypeAlphabet
:
case
config
.
TraceTypeAlphabet
:
...
@@ -344,7 +363,6 @@ func requiredArgs(traceType config.TraceType) map[string]string {
...
@@ -344,7 +363,6 @@ func requiredArgs(traceType config.TraceType) map[string]string {
args
[
"--cannon-bin"
]
=
cannonBin
args
[
"--cannon-bin"
]
=
cannonBin
args
[
"--cannon-server"
]
=
cannonServer
args
[
"--cannon-server"
]
=
cannonServer
args
[
"--cannon-prestate"
]
=
cannonPreState
args
[
"--cannon-prestate"
]
=
cannonPreState
args
[
"--cannon-datadir"
]
=
cannonDatadir
args
[
"--cannon-l2"
]
=
cannonL2
args
[
"--cannon-l2"
]
=
cannonL2
}
}
return
args
return
args
...
...
op-challenger/config/config.go
View file @
a382b9e2
...
@@ -3,6 +3,7 @@ package config
...
@@ -3,6 +3,7 @@ package config
import
(
import
(
"errors"
"errors"
"fmt"
"fmt"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
...
@@ -14,7 +15,7 @@ import (
...
@@ -14,7 +15,7 @@ import (
var
(
var
(
ErrMissingTraceType
=
errors
.
New
(
"missing trace type"
)
ErrMissingTraceType
=
errors
.
New
(
"missing trace type"
)
ErrMissing
CannonDatadir
=
errors
.
New
(
"missing cannon
datadir"
)
ErrMissing
Datadir
=
errors
.
New
(
"missing
datadir"
)
ErrMissingCannonL2
=
errors
.
New
(
"missing cannon L2"
)
ErrMissingCannonL2
=
errors
.
New
(
"missing cannon L2"
)
ErrMissingCannonBin
=
errors
.
New
(
"missing cannon bin"
)
ErrMissingCannonBin
=
errors
.
New
(
"missing cannon bin"
)
ErrMissingCannonServer
=
errors
.
New
(
"missing cannon server"
)
ErrMissingCannonServer
=
errors
.
New
(
"missing cannon server"
)
...
@@ -73,7 +74,14 @@ func ValidTraceType(value TraceType) bool {
...
@@ -73,7 +74,14 @@ func ValidTraceType(value TraceType) bool {
return
false
return
false
}
}
const
DefaultCannonSnapshotFreq
=
uint
(
1
_000_000_000
)
const
(
DefaultCannonSnapshotFreq
=
uint
(
1
_000_000_000
)
// DefaultGameWindow is the default maximum time duration in the past
// that the challenger will look for games to progress.
// The default value is 11 days, which is a 4 day resolution buffer
// plus the 7 day game finalization window.
DefaultGameWindow
=
time
.
Duration
(
11
*
24
*
time
.
Hour
)
)
// Config is a well typed config that is parsed from the CLI params.
// Config is a well typed config that is parsed from the CLI params.
// This also contains config options for auxiliary services.
// This also contains config options for auxiliary services.
...
@@ -82,7 +90,9 @@ type Config struct {
...
@@ -82,7 +90,9 @@ type Config struct {
L1EthRpc
string
// L1 RPC Url
L1EthRpc
string
// L1 RPC Url
GameFactoryAddress
common
.
Address
// Address of the dispute game factory
GameFactoryAddress
common
.
Address
// Address of the dispute game factory
GameAllowlist
[]
common
.
Address
// Allowlist of fault game addresses
GameAllowlist
[]
common
.
Address
// Allowlist of fault game addresses
GameWindow
time
.
Duration
// Maximum time duration to look for games to progress
AgreeWithProposedOutput
bool
// Temporary config if we agree or disagree with the posted output
AgreeWithProposedOutput
bool
// Temporary config if we agree or disagree with the posted output
Datadir
string
// Data Directory
TraceType
TraceType
// Type of trace
TraceType
TraceType
// Type of trace
...
@@ -96,7 +106,6 @@ type Config struct {
...
@@ -96,7 +106,6 @@ type Config struct {
CannonNetwork
string
CannonNetwork
string
CannonRollupConfigPath
string
CannonRollupConfigPath
string
CannonL2GenesisPath
string
CannonL2GenesisPath
string
CannonDatadir
string
// Cannon Data Directory
CannonL2
string
// L2 RPC Url
CannonL2
string
// L2 RPC Url
CannonSnapshotFreq
uint
// Frequency of snapshots to create when executing cannon (in VM instructions)
CannonSnapshotFreq
uint
// Frequency of snapshots to create when executing cannon (in VM instructions)
...
@@ -110,6 +119,7 @@ func NewConfig(
...
@@ -110,6 +119,7 @@ func NewConfig(
l1EthRpc
string
,
l1EthRpc
string
,
traceType
TraceType
,
traceType
TraceType
,
agreeWithProposedOutput
bool
,
agreeWithProposedOutput
bool
,
datadir
string
,
)
Config
{
)
Config
{
return
Config
{
return
Config
{
L1EthRpc
:
l1EthRpc
,
L1EthRpc
:
l1EthRpc
,
...
@@ -123,7 +133,10 @@ func NewConfig(
...
@@ -123,7 +133,10 @@ func NewConfig(
MetricsConfig
:
opmetrics
.
DefaultCLIConfig
(),
MetricsConfig
:
opmetrics
.
DefaultCLIConfig
(),
PprofConfig
:
oppprof
.
DefaultCLIConfig
(),
PprofConfig
:
oppprof
.
DefaultCLIConfig
(),
Datadir
:
datadir
,
CannonSnapshotFreq
:
DefaultCannonSnapshotFreq
,
CannonSnapshotFreq
:
DefaultCannonSnapshotFreq
,
GameWindow
:
DefaultGameWindow
,
}
}
}
}
...
@@ -137,6 +150,9 @@ func (c Config) Check() error {
...
@@ -137,6 +150,9 @@ func (c Config) Check() error {
if
c
.
TraceType
==
""
{
if
c
.
TraceType
==
""
{
return
ErrMissingTraceType
return
ErrMissingTraceType
}
}
if
c
.
Datadir
==
""
{
return
ErrMissingDatadir
}
if
c
.
TraceType
==
TraceTypeCannon
{
if
c
.
TraceType
==
TraceTypeCannon
{
if
c
.
CannonBin
==
""
{
if
c
.
CannonBin
==
""
{
return
ErrMissingCannonBin
return
ErrMissingCannonBin
...
@@ -165,9 +181,6 @@ func (c Config) Check() error {
...
@@ -165,9 +181,6 @@ func (c Config) Check() error {
if
c
.
CannonAbsolutePreState
==
""
{
if
c
.
CannonAbsolutePreState
==
""
{
return
ErrMissingCannonAbsolutePreState
return
ErrMissingCannonAbsolutePreState
}
}
if
c
.
CannonDatadir
==
""
{
return
ErrMissingCannonDatadir
}
if
c
.
CannonL2
==
""
{
if
c
.
CannonL2
==
""
{
return
ErrMissingCannonL2
return
ErrMissingCannonL2
}
}
...
...
op-challenger/config/config_test.go
View file @
a382b9e2
...
@@ -17,13 +17,13 @@ var (
...
@@ -17,13 +17,13 @@ var (
validCannonOpProgramBin
=
"./bin/op-program"
validCannonOpProgramBin
=
"./bin/op-program"
validCannonNetwork
=
"mainnet"
validCannonNetwork
=
"mainnet"
validCannonAbsolutPreState
=
"pre.json"
validCannonAbsolutPreState
=
"pre.json"
valid
CannonDatadir
=
"/tmp/cannon
"
valid
Datadir
=
"/tmp/data
"
validCannonL2
=
"http://localhost:9545"
validCannonL2
=
"http://localhost:9545"
agreeWithProposedOutput
=
true
agreeWithProposedOutput
=
true
)
)
func
validConfig
(
traceType
TraceType
)
Config
{
func
validConfig
(
traceType
TraceType
)
Config
{
cfg
:=
NewConfig
(
validGameFactoryAddress
,
validL1EthRpc
,
traceType
,
agreeWithProposedOutput
)
cfg
:=
NewConfig
(
validGameFactoryAddress
,
validL1EthRpc
,
traceType
,
agreeWithProposedOutput
,
validDatadir
)
switch
traceType
{
switch
traceType
{
case
TraceTypeAlphabet
:
case
TraceTypeAlphabet
:
cfg
.
AlphabetTrace
=
validAlphabetTrace
cfg
.
AlphabetTrace
=
validAlphabetTrace
...
@@ -31,7 +31,6 @@ func validConfig(traceType TraceType) Config {
...
@@ -31,7 +31,6 @@ func validConfig(traceType TraceType) Config {
cfg
.
CannonBin
=
validCannonBin
cfg
.
CannonBin
=
validCannonBin
cfg
.
CannonServer
=
validCannonOpProgramBin
cfg
.
CannonServer
=
validCannonOpProgramBin
cfg
.
CannonAbsolutePreState
=
validCannonAbsolutPreState
cfg
.
CannonAbsolutePreState
=
validCannonAbsolutPreState
cfg
.
CannonDatadir
=
validCannonDatadir
cfg
.
CannonL2
=
validCannonL2
cfg
.
CannonL2
=
validCannonL2
cfg
.
CannonNetwork
=
validCannonNetwork
cfg
.
CannonNetwork
=
validCannonNetwork
}
}
...
@@ -99,10 +98,10 @@ func TestCannonAbsolutePreStateRequired(t *testing.T) {
...
@@ -99,10 +98,10 @@ func TestCannonAbsolutePreStateRequired(t *testing.T) {
require
.
ErrorIs
(
t
,
config
.
Check
(),
ErrMissingCannonAbsolutePreState
)
require
.
ErrorIs
(
t
,
config
.
Check
(),
ErrMissingCannonAbsolutePreState
)
}
}
func
Test
Cannon
DatadirRequired
(
t
*
testing
.
T
)
{
func
TestDatadirRequired
(
t
*
testing
.
T
)
{
config
:=
validConfig
(
TraceType
Cannon
)
config
:=
validConfig
(
TraceType
Alphabet
)
config
.
Cannon
Datadir
=
""
config
.
Datadir
=
""
require
.
ErrorIs
(
t
,
config
.
Check
(),
ErrMissing
Cannon
Datadir
)
require
.
ErrorIs
(
t
,
config
.
Check
(),
ErrMissingDatadir
)
}
}
func
TestCannonL2Required
(
t
*
testing
.
T
)
{
func
TestCannonL2Required
(
t
*
testing
.
T
)
{
...
...
op-challenger/fault/abi_test.go
View file @
a382b9e2
...
@@ -55,7 +55,7 @@ func TestBuildFaultDefendData(t *testing.T) {
...
@@ -55,7 +55,7 @@ func TestBuildFaultDefendData(t *testing.T) {
_
,
opts
,
_
,
contract
,
err
:=
setupFaultDisputeGame
()
_
,
opts
,
_
,
contract
,
err
:=
setupFaultDisputeGame
()
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
responder
,
_
:=
newTestFaultResponder
(
t
,
false
)
responder
,
_
:=
newTestFaultResponder
(
t
)
data
,
err
:=
responder
.
buildFaultDefendData
(
1
,
[
32
]
byte
{
0x02
,
0x03
})
data
,
err
:=
responder
.
buildFaultDefendData
(
1
,
[
32
]
byte
{
0x02
,
0x03
})
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
...
@@ -72,7 +72,7 @@ func TestBuildFaultAttackData(t *testing.T) {
...
@@ -72,7 +72,7 @@ func TestBuildFaultAttackData(t *testing.T) {
_
,
opts
,
_
,
contract
,
err
:=
setupFaultDisputeGame
()
_
,
opts
,
_
,
contract
,
err
:=
setupFaultDisputeGame
()
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
responder
,
_
:=
newTestFaultResponder
(
t
,
false
)
responder
,
_
:=
newTestFaultResponder
(
t
)
data
,
err
:=
responder
.
buildFaultAttackData
(
1
,
[
32
]
byte
{
0x02
,
0x03
})
data
,
err
:=
responder
.
buildFaultAttackData
(
1
,
[
32
]
byte
{
0x02
,
0x03
})
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
...
@@ -89,7 +89,7 @@ func TestBuildFaultStepData(t *testing.T) {
...
@@ -89,7 +89,7 @@ func TestBuildFaultStepData(t *testing.T) {
_
,
opts
,
_
,
contract
,
err
:=
setupFaultDisputeGame
()
_
,
opts
,
_
,
contract
,
err
:=
setupFaultDisputeGame
()
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
responder
,
_
:=
newTestFaultResponder
(
t
,
false
)
responder
,
_
:=
newTestFaultResponder
(
t
)
data
,
err
:=
responder
.
buildStepTxData
(
types
.
StepCallData
{
data
,
err
:=
responder
.
buildStepTxData
(
types
.
StepCallData
{
ClaimIndex
:
2
,
ClaimIndex
:
2
,
...
...
op-challenger/fault/agent.go
View file @
a382b9e2
...
@@ -13,7 +13,7 @@ import (
...
@@ -13,7 +13,7 @@ import (
// Responder takes a response action & executes.
// Responder takes a response action & executes.
// For full op-challenger this means executing the transaction on chain.
// For full op-challenger this means executing the transaction on chain.
type
Responder
interface
{
type
Responder
interface
{
Ca
nResolve
(
ctx
context
.
Context
)
bool
Ca
llResolve
(
ctx
context
.
Context
)
(
types
.
GameStatus
,
error
)
Resolve
(
ctx
context
.
Context
)
error
Resolve
(
ctx
context
.
Context
)
error
Respond
(
ctx
context
.
Context
,
response
types
.
Claim
)
error
Respond
(
ctx
context
.
Context
,
response
types
.
Claim
)
error
Step
(
ctx
context
.
Context
,
stepData
types
.
StepCallData
)
error
Step
(
ctx
context
.
Context
,
stepData
types
.
StepCallData
)
error
...
@@ -65,10 +65,27 @@ func (a *Agent) Act(ctx context.Context) error {
...
@@ -65,10 +65,27 @@ func (a *Agent) Act(ctx context.Context) error {
return
nil
return
nil
}
}
// shouldResolve returns true if the agent should resolve the game.
// This method will return false if the game is still in progress.
func
(
a
*
Agent
)
shouldResolve
(
ctx
context
.
Context
,
status
types
.
GameStatus
)
bool
{
expected
:=
types
.
GameStatusDefenderWon
if
a
.
agreeWithProposedOutput
{
expected
=
types
.
GameStatusChallengerWon
}
if
expected
!=
status
{
a
.
log
.
Warn
(
"Game will be lost"
,
"expected"
,
expected
,
"actual"
,
status
)
}
return
expected
==
status
}
// tryResolve resolves the game if it is in a terminal state
// tryResolve resolves the game if it is in a terminal state
// and returns true if the game resolves successfully.
// and returns true if the game resolves successfully.
func
(
a
*
Agent
)
tryResolve
(
ctx
context
.
Context
)
bool
{
func
(
a
*
Agent
)
tryResolve
(
ctx
context
.
Context
)
bool
{
if
!
a
.
responder
.
CanResolve
(
ctx
)
{
status
,
err
:=
a
.
responder
.
CallResolve
(
ctx
)
if
err
!=
nil
{
return
false
}
if
!
a
.
shouldResolve
(
ctx
,
status
)
{
return
false
return
false
}
}
a
.
log
.
Info
(
"Resolving game"
)
a
.
log
.
Info
(
"Resolving game"
)
...
...
op-challenger/fault/agent_test.go
0 → 100644
View file @
a382b9e2
package
fault
import
(
"context"
"testing"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-node/testlog"
)
// TestShouldResolve tests the resolution logic.
func
TestShouldResolve
(
t
*
testing
.
T
)
{
log
:=
testlog
.
Logger
(
t
,
log
.
LvlCrit
)
t
.
Run
(
"AgreeWithProposedOutput"
,
func
(
t
*
testing
.
T
)
{
agent
:=
NewAgent
(
nil
,
0
,
nil
,
nil
,
nil
,
true
,
log
)
require
.
False
(
t
,
agent
.
shouldResolve
(
context
.
Background
(),
types
.
GameStatusDefenderWon
))
require
.
True
(
t
,
agent
.
shouldResolve
(
context
.
Background
(),
types
.
GameStatusChallengerWon
))
require
.
False
(
t
,
agent
.
shouldResolve
(
context
.
Background
(),
types
.
GameStatusInProgress
))
})
t
.
Run
(
"DisagreeWithProposedOutput"
,
func
(
t
*
testing
.
T
)
{
agent
:=
NewAgent
(
nil
,
0
,
nil
,
nil
,
nil
,
false
,
log
)
require
.
True
(
t
,
agent
.
shouldResolve
(
context
.
Background
(),
types
.
GameStatusDefenderWon
))
require
.
False
(
t
,
agent
.
shouldResolve
(
context
.
Background
(),
types
.
GameStatusChallengerWon
))
require
.
False
(
t
,
agent
.
shouldResolve
(
context
.
Background
(),
types
.
GameStatusInProgress
))
})
}
op-challenger/fault/caller.go
View file @
a382b9e2
...
@@ -8,7 +8,6 @@ import (
...
@@ -8,7 +8,6 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
)
type
FaultDisputeGameCaller
interface
{
type
FaultDisputeGameCaller
interface
{
...
@@ -26,7 +25,7 @@ func NewFaultCaller(caller FaultDisputeGameCaller) *FaultCaller {
...
@@ -26,7 +25,7 @@ func NewFaultCaller(caller FaultDisputeGameCaller) *FaultCaller {
}
}
}
}
func
NewFaultCallerFromBindings
(
fdgAddr
common
.
Address
,
client
*
ethclient
.
Client
)
(
*
FaultCaller
,
error
)
{
func
NewFaultCallerFromBindings
(
fdgAddr
common
.
Address
,
client
bind
.
ContractCaller
)
(
*
FaultCaller
,
error
)
{
caller
,
err
:=
bindings
.
NewFaultDisputeGameCaller
(
fdgAddr
,
client
)
caller
,
err
:=
bindings
.
NewFaultDisputeGameCaller
(
fdgAddr
,
client
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
...
op-challenger/fault/cannon/executor_test.go
View file @
a382b9e2
...
@@ -21,10 +21,9 @@ const execTestCannonPrestate = "/foo/pre.json"
...
@@ -21,10 +21,9 @@ const execTestCannonPrestate = "/foo/pre.json"
func
TestGenerateProof
(
t
*
testing
.
T
)
{
func
TestGenerateProof
(
t
*
testing
.
T
)
{
input
:=
"starting.json"
input
:=
"starting.json"
cfg
:=
config
.
NewConfig
(
common
.
Address
{
0xbb
},
"http://localhost:8888"
,
config
.
TraceTypeCannon
,
true
)
tempDir
:=
t
.
TempDir
()
tempDir
:=
t
.
TempDir
()
dir
:=
filepath
.
Join
(
tempDir
,
"gameDir"
)
dir
:=
filepath
.
Join
(
tempDir
,
"gameDir"
)
cfg
.
CannonDatadir
=
tempDir
cfg
:=
config
.
NewConfig
(
common
.
Address
{
0xbb
},
"http://localhost:8888"
,
config
.
TraceTypeCannon
,
true
,
tempDir
)
cfg
.
CannonAbsolutePreState
=
"pre.json"
cfg
.
CannonAbsolutePreState
=
"pre.json"
cfg
.
CannonBin
=
"./bin/cannon"
cfg
.
CannonBin
=
"./bin/cannon"
cfg
.
CannonServer
=
"./bin/op-program"
cfg
.
CannonServer
=
"./bin/op-program"
...
...
op-challenger/fault/cannon/provider.go
View file @
a382b9e2
...
@@ -50,7 +50,7 @@ type CannonTraceProvider struct {
...
@@ -50,7 +50,7 @@ type CannonTraceProvider struct {
lastProof
*
proofData
lastProof
*
proofData
}
}
func
NewTraceProvider
(
ctx
context
.
Context
,
logger
log
.
Logger
,
cfg
*
config
.
Config
,
l1Client
bind
.
ContractCaller
,
gameAddr
common
.
Address
)
(
*
CannonTraceProvider
,
error
)
{
func
NewTraceProvider
(
ctx
context
.
Context
,
logger
log
.
Logger
,
cfg
*
config
.
Config
,
l1Client
bind
.
ContractCaller
,
dir
string
,
gameAddr
common
.
Address
)
(
*
CannonTraceProvider
,
error
)
{
l2Client
,
err
:=
ethclient
.
DialContext
(
ctx
,
cfg
.
CannonL2
)
l2Client
,
err
:=
ethclient
.
DialContext
(
ctx
,
cfg
.
CannonL2
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"dial l2 client %v: %w"
,
cfg
.
CannonL2
,
err
)
return
nil
,
fmt
.
Errorf
(
"dial l2 client %v: %w"
,
cfg
.
CannonL2
,
err
)
...
@@ -64,11 +64,10 @@ func NewTraceProvider(ctx context.Context, logger log.Logger, cfg *config.Config
...
@@ -64,11 +64,10 @@ func NewTraceProvider(ctx context.Context, logger log.Logger, cfg *config.Config
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"fetch local game inputs: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"fetch local game inputs: %w"
,
err
)
}
}
return
NewTraceProviderFromInputs
(
logger
,
cfg
,
gameAddr
.
Hex
(),
localInputs
),
nil
return
NewTraceProviderFromInputs
(
logger
,
cfg
,
localInputs
,
dir
),
nil
}
}
func
NewTraceProviderFromInputs
(
logger
log
.
Logger
,
cfg
*
config
.
Config
,
gameDirName
string
,
localInputs
LocalGameInputs
)
*
CannonTraceProvider
{
func
NewTraceProviderFromInputs
(
logger
log
.
Logger
,
cfg
*
config
.
Config
,
localInputs
LocalGameInputs
,
dir
string
)
*
CannonTraceProvider
{
dir
:=
filepath
.
Join
(
cfg
.
CannonDatadir
,
gameDirName
)
return
&
CannonTraceProvider
{
return
&
CannonTraceProvider
{
logger
:
logger
,
logger
:
logger
,
dir
:
dir
,
dir
:
dir
,
...
...
op-challenger/fault/cannon/provider_test.go
View file @
a382b9e2
...
@@ -11,7 +11,6 @@ import (
...
@@ -11,7 +11,6 @@ import (
"testing"
"testing"
"github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
...
@@ -189,21 +188,6 @@ func TestAbsolutePreState(t *testing.T) {
...
@@ -189,21 +188,6 @@ func TestAbsolutePreState(t *testing.T) {
})
})
}
}
func
TestUseGameSpecificSubdir
(
t
*
testing
.
T
)
{
tempDir
:=
t
.
TempDir
()
dataDir
:=
filepath
.
Join
(
tempDir
,
"data"
)
setupPreState
(
t
,
tempDir
,
"state.json"
)
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlInfo
)
cfg
:=
&
config
.
Config
{
CannonAbsolutePreState
:
filepath
.
Join
(
tempDir
,
"state.json"
),
CannonDatadir
:
dataDir
,
}
gameDirName
:=
"gameSubdir"
localInputs
:=
LocalGameInputs
{}
provider
:=
NewTraceProviderFromInputs
(
logger
,
cfg
,
gameDirName
,
localInputs
)
require
.
Equal
(
t
,
filepath
.
Join
(
dataDir
,
gameDirName
),
provider
.
dir
,
"should use game specific subdir"
)
}
func
setupPreState
(
t
*
testing
.
T
,
dataDir
string
,
filename
string
)
{
func
setupPreState
(
t
*
testing
.
T
,
dataDir
string
,
filename
string
)
{
srcDir
:=
filepath
.
Join
(
"test_data"
)
srcDir
:=
filepath
.
Join
(
"test_data"
)
path
:=
filepath
.
Join
(
srcDir
,
filename
)
path
:=
filepath
.
Join
(
srcDir
,
filename
)
...
...
op-challenger/fault/disk.go
0 → 100644
View file @
a382b9e2
package
fault
import
(
"fmt"
"os"
"path/filepath"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/hashicorp/go-multierror"
"golang.org/x/exp/slices"
)
const
gameDirPrefix
=
"game-"
// diskManager coordinates
type
diskManager
struct
{
datadir
string
}
func
newDiskManager
(
dir
string
)
*
diskManager
{
return
&
diskManager
{
datadir
:
dir
}
}
func
(
d
*
diskManager
)
DirForGame
(
addr
common
.
Address
)
string
{
return
filepath
.
Join
(
d
.
datadir
,
gameDirPrefix
+
addr
.
Hex
())
}
func
(
d
*
diskManager
)
RemoveAllExcept
(
keep
[]
common
.
Address
)
error
{
entries
,
err
:=
os
.
ReadDir
(
d
.
datadir
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to list directory: %w"
,
err
)
}
var
result
error
for
_
,
entry
:=
range
entries
{
if
!
entry
.
IsDir
()
||
!
strings
.
HasPrefix
(
entry
.
Name
(),
gameDirPrefix
)
{
// Skip files and directories that don't have the game directory prefix.
// While random content shouldn't be in our datadir, we want to avoid
// deleting things like OS generated files.
continue
}
name
:=
entry
.
Name
()[
len
(
gameDirPrefix
)
:
]
addr
:=
common
.
HexToAddress
(
name
)
if
addr
==
(
common
.
Address
{})
{
// Couldn't parse the directory name to an address so mustn't be a game directory
continue
}
if
slices
.
Contains
(
keep
,
addr
)
{
// We need to preserve this data
continue
}
if
err
:=
os
.
RemoveAll
(
filepath
.
Join
(
d
.
datadir
,
entry
.
Name
()));
err
!=
nil
{
result
=
multierror
.
Append
(
result
,
err
)
}
}
return
result
}
op-challenger/fault/disk_test.go
0 → 100644
View file @
a382b9e2
package
fault
import
(
"os"
"path/filepath"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
func
TestDiskManager_DirForGame
(
t
*
testing
.
T
)
{
baseDir
:=
t
.
TempDir
()
addr
:=
common
.
Address
{
0x53
}
disk
:=
newDiskManager
(
baseDir
)
result
:=
disk
.
DirForGame
(
addr
)
require
.
Equal
(
t
,
filepath
.
Join
(
baseDir
,
gameDirPrefix
+
addr
.
Hex
()),
result
)
}
func
TestDiskManager_RemoveAllExcept
(
t
*
testing
.
T
)
{
baseDir
:=
t
.
TempDir
()
keep
:=
common
.
Address
{
0x53
}
delete
:=
common
.
Address
{
0xaa
}
disk
:=
newDiskManager
(
baseDir
)
keepDir
:=
disk
.
DirForGame
(
keep
)
deleteDir
:=
disk
.
DirForGame
(
delete
)
unexpectedFile
:=
filepath
.
Join
(
baseDir
,
"file.txt"
)
require
.
NoError
(
t
,
os
.
WriteFile
(
unexpectedFile
,
[]
byte
(
"test"
),
0644
))
unexpectedDir
:=
filepath
.
Join
(
baseDir
,
"notagame"
)
require
.
NoError
(
t
,
os
.
MkdirAll
(
unexpectedDir
,
0777
))
invalidHexDir
:=
filepath
.
Join
(
baseDir
,
gameDirPrefix
+
"0xNOPE"
)
require
.
NoError
(
t
,
os
.
MkdirAll
(
invalidHexDir
,
0777
))
populateDir
:=
func
(
dir
string
)
[]
string
{
require
.
NoError
(
t
,
os
.
MkdirAll
(
dir
,
0777
))
file1
:=
filepath
.
Join
(
dir
,
"test.txt"
)
require
.
NoError
(
t
,
os
.
WriteFile
(
file1
,
[]
byte
(
"foo"
),
0644
))
nestedDirs
:=
filepath
.
Join
(
dir
,
"subdir"
,
"deep"
)
require
.
NoError
(
t
,
os
.
MkdirAll
(
nestedDirs
,
0777
))
file2
:=
filepath
.
Join
(
nestedDirs
,
".foo.txt"
)
require
.
NoError
(
t
,
os
.
WriteFile
(
file2
,
[]
byte
(
"foo"
),
0644
))
return
[]
string
{
file1
,
file2
}
}
keepFiles
:=
populateDir
(
keepDir
)
populateDir
(
deleteDir
)
require
.
NoError
(
t
,
disk
.
RemoveAllExcept
([]
common
.
Address
{
keep
}))
require
.
NoDirExists
(
t
,
deleteDir
,
"should have deleted directory"
)
for
_
,
file
:=
range
keepFiles
{
require
.
FileExists
(
t
,
file
,
"should have kept file for active game"
)
}
require
.
FileExists
(
t
,
unexpectedFile
,
"should not delete unexpected file"
)
require
.
DirExists
(
t
,
unexpectedDir
,
"should not delete unexpected dir"
)
require
.
DirExists
(
t
,
invalidHexDir
,
"should not delete dir with invalid address"
)
}
op-challenger/fault/factory.go
View file @
a382b9e2
...
@@ -43,7 +43,7 @@ func NewGameLoader(caller MinimalDisputeGameFactoryCaller) *gameLoader {
...
@@ -43,7 +43,7 @@ func NewGameLoader(caller MinimalDisputeGameFactoryCaller) *gameLoader {
}
}
// FetchAllGamesAtBlock fetches all dispute games from the factory at a given block number.
// FetchAllGamesAtBlock fetches all dispute games from the factory at a given block number.
func
(
l
*
gameLoader
)
FetchAllGamesAtBlock
(
ctx
context
.
Context
,
blockNumber
*
big
.
Int
)
([]
FaultDisputeGame
,
error
)
{
func
(
l
*
gameLoader
)
FetchAllGamesAtBlock
(
ctx
context
.
Context
,
earliestTimestamp
uint64
,
blockNumber
*
big
.
Int
)
([]
FaultDisputeGame
,
error
)
{
if
blockNumber
==
nil
{
if
blockNumber
==
nil
{
return
nil
,
ErrMissingBlockNumber
return
nil
,
ErrMissingBlockNumber
}
}
...
@@ -56,14 +56,19 @@ func (l *gameLoader) FetchAllGamesAtBlock(ctx context.Context, blockNumber *big.
...
@@ -56,14 +56,19 @@ func (l *gameLoader) FetchAllGamesAtBlock(ctx context.Context, blockNumber *big.
return
nil
,
fmt
.
Errorf
(
"failed to fetch game count: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to fetch game count: %w"
,
err
)
}
}
games
:=
make
([]
FaultDisputeGame
,
gameCount
.
Uint64
())
games
:=
make
([]
FaultDisputeGame
,
0
)
for
i
:=
uint64
(
0
);
i
<
gameCount
.
Uint64
();
i
++
{
if
gameCount
.
Uint64
()
==
0
{
game
,
err
:=
l
.
caller
.
GameAtIndex
(
callOpts
,
big
.
NewInt
(
int64
(
i
)))
return
games
,
nil
}
for
i
:=
gameCount
.
Uint64
();
i
>
0
;
i
--
{
game
,
err
:=
l
.
caller
.
GameAtIndex
(
callOpts
,
big
.
NewInt
(
int64
(
i
-
1
)))
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to fetch game at index %d: %w"
,
i
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to fetch game at index %d: %w"
,
i
,
err
)
}
}
if
game
.
Timestamp
<
earliestTimestamp
{
games
[
i
]
=
game
break
}
games
=
append
(
games
,
game
)
}
}
return
games
,
nil
return
games
,
nil
...
...
op-challenger/fault/factory_test.go
View file @
a382b9e2
...
@@ -25,6 +25,7 @@ func TestGameLoader_FetchAllGames(t *testing.T) {
...
@@ -25,6 +25,7 @@ func TestGameLoader_FetchAllGames(t *testing.T) {
tests
:=
[]
struct
{
tests
:=
[]
struct
{
name
string
name
string
caller
*
mockMinimalDisputeGameFactoryCaller
caller
*
mockMinimalDisputeGameFactoryCaller
earliest
uint64
blockNumber
*
big
.
Int
blockNumber
*
big
.
Int
expectedErr
error
expectedErr
error
expectedLen
int
expectedLen
int
...
@@ -33,35 +34,36 @@ func TestGameLoader_FetchAllGames(t *testing.T) {
...
@@ -33,35 +34,36 @@ func TestGameLoader_FetchAllGames(t *testing.T) {
name
:
"success"
,
name
:
"success"
,
caller
:
newMockMinimalDisputeGameFactoryCaller
(
10
,
false
,
false
),
caller
:
newMockMinimalDisputeGameFactoryCaller
(
10
,
false
,
false
),
blockNumber
:
big
.
NewInt
(
1
),
blockNumber
:
big
.
NewInt
(
1
),
expectedErr
:
nil
,
expectedLen
:
10
,
expectedLen
:
10
,
},
},
{
name
:
"expired game ignored"
,
caller
:
newMockMinimalDisputeGameFactoryCaller
(
10
,
false
,
false
),
earliest
:
500
,
blockNumber
:
big
.
NewInt
(
1
),
expectedLen
:
5
,
},
{
{
name
:
"game count error"
,
name
:
"game count error"
,
caller
:
newMockMinimalDisputeGameFactoryCaller
(
10
,
true
,
false
),
caller
:
newMockMinimalDisputeGameFactoryCaller
(
10
,
true
,
false
),
blockNumber
:
big
.
NewInt
(
1
),
blockNumber
:
big
.
NewInt
(
1
),
expectedErr
:
gameCountErr
,
expectedErr
:
gameCountErr
,
expectedLen
:
0
,
},
},
{
{
name
:
"game index error"
,
name
:
"game index error"
,
caller
:
newMockMinimalDisputeGameFactoryCaller
(
10
,
false
,
true
),
caller
:
newMockMinimalDisputeGameFactoryCaller
(
10
,
false
,
true
),
blockNumber
:
big
.
NewInt
(
1
),
blockNumber
:
big
.
NewInt
(
1
),
expectedErr
:
gameIndexErr
,
expectedErr
:
gameIndexErr
,
expectedLen
:
0
,
},
},
{
{
name
:
"no games"
,
name
:
"no games"
,
caller
:
newMockMinimalDisputeGameFactoryCaller
(
0
,
false
,
false
),
caller
:
newMockMinimalDisputeGameFactoryCaller
(
0
,
false
,
false
),
blockNumber
:
big
.
NewInt
(
1
),
blockNumber
:
big
.
NewInt
(
1
),
expectedErr
:
nil
,
expectedLen
:
0
,
},
},
{
{
name
:
"missing block number"
,
name
:
"missing block number"
,
caller
:
newMockMinimalDisputeGameFactoryCaller
(
0
,
false
,
false
),
caller
:
newMockMinimalDisputeGameFactoryCaller
(
0
,
false
,
false
),
expectedErr
:
ErrMissingBlockNumber
,
expectedErr
:
ErrMissingBlockNumber
,
expectedLen
:
0
,
},
},
}
}
...
@@ -72,10 +74,11 @@ func TestGameLoader_FetchAllGames(t *testing.T) {
...
@@ -72,10 +74,11 @@ func TestGameLoader_FetchAllGames(t *testing.T) {
t
.
Parallel
()
t
.
Parallel
()
loader
:=
NewGameLoader
(
test
.
caller
)
loader
:=
NewGameLoader
(
test
.
caller
)
games
,
err
:=
loader
.
FetchAllGamesAtBlock
(
context
.
Background
(),
test
.
blockNumber
)
games
,
err
:=
loader
.
FetchAllGamesAtBlock
(
context
.
Background
(),
test
.
earliest
,
test
.
blockNumber
)
require
.
ErrorIs
(
t
,
err
,
test
.
expectedErr
)
require
.
ErrorIs
(
t
,
err
,
test
.
expectedErr
)
require
.
Len
(
t
,
games
,
test
.
expectedLen
)
require
.
Len
(
t
,
games
,
test
.
expectedLen
)
expectedGames
:=
test
.
caller
.
games
expectedGames
:=
test
.
caller
.
games
expectedGames
=
expectedGames
[
len
(
expectedGames
)
-
test
.
expectedLen
:
]
if
test
.
expectedErr
!=
nil
{
if
test
.
expectedErr
!=
nil
{
expectedGames
=
make
([]
FaultDisputeGame
,
0
)
expectedGames
=
make
([]
FaultDisputeGame
,
0
)
}
}
...
@@ -90,7 +93,7 @@ func generateMockGames(count uint64) []FaultDisputeGame {
...
@@ -90,7 +93,7 @@ func generateMockGames(count uint64) []FaultDisputeGame {
for
i
:=
uint64
(
0
);
i
<
count
;
i
++
{
for
i
:=
uint64
(
0
);
i
<
count
;
i
++
{
games
[
i
]
=
FaultDisputeGame
{
games
[
i
]
=
FaultDisputeGame
{
Proxy
:
common
.
BigToAddress
(
big
.
NewInt
(
int64
(
i
))),
Proxy
:
common
.
BigToAddress
(
big
.
NewInt
(
int64
(
i
))),
Timestamp
:
i
,
Timestamp
:
i
*
100
,
}
}
}
}
...
...
op-challenger/fault/monitor.go
View file @
a382b9e2
...
@@ -15,29 +15,47 @@ type gamePlayer interface {
...
@@ -15,29 +15,47 @@ type gamePlayer interface {
ProgressGame
(
ctx
context
.
Context
)
bool
ProgressGame
(
ctx
context
.
Context
)
bool
}
}
type
playerCreator
func
(
address
common
.
Address
)
(
gamePlayer
,
error
)
type
playerCreator
func
(
address
common
.
Address
,
dir
string
)
(
gamePlayer
,
error
)
type
blockNumberFetcher
func
(
ctx
context
.
Context
)
(
uint64
,
error
)
type
blockNumberFetcher
func
(
ctx
context
.
Context
)
(
uint64
,
error
)
// gameSource loads information about the games available to play
// gameSource loads information about the games available to play
type
gameSource
interface
{
type
gameSource
interface
{
FetchAllGamesAtBlock
(
ctx
context
.
Context
,
blockNumber
*
big
.
Int
)
([]
FaultDisputeGame
,
error
)
FetchAllGamesAtBlock
(
ctx
context
.
Context
,
earliest
uint64
,
blockNumber
*
big
.
Int
)
([]
FaultDisputeGame
,
error
)
}
type
gameDiskAllocator
interface
{
DirForGame
(
common
.
Address
)
string
RemoveAllExcept
([]
common
.
Address
)
error
}
}
type
gameMonitor
struct
{
type
gameMonitor
struct
{
logger
log
.
Logger
logger
log
.
Logger
clock
clock
.
Clock
clock
clock
.
Clock
diskManager
gameDiskAllocator
source
gameSource
source
gameSource
gameWindow
time
.
Duration
createPlayer
playerCreator
createPlayer
playerCreator
fetchBlockNumber
blockNumberFetcher
fetchBlockNumber
blockNumberFetcher
allowedGames
[]
common
.
Address
allowedGames
[]
common
.
Address
players
map
[
common
.
Address
]
gamePlayer
players
map
[
common
.
Address
]
gamePlayer
}
}
func
newGameMonitor
(
logger
log
.
Logger
,
cl
clock
.
Clock
,
fetchBlockNumber
blockNumberFetcher
,
allowedGames
[]
common
.
Address
,
source
gameSource
,
createGame
playerCreator
)
*
gameMonitor
{
func
newGameMonitor
(
logger
log
.
Logger
,
gameWindow
time
.
Duration
,
cl
clock
.
Clock
,
disk
gameDiskAllocator
,
fetchBlockNumber
blockNumberFetcher
,
allowedGames
[]
common
.
Address
,
source
gameSource
,
createGame
playerCreator
,
)
*
gameMonitor
{
return
&
gameMonitor
{
return
&
gameMonitor
{
logger
:
logger
,
logger
:
logger
,
clock
:
cl
,
clock
:
cl
,
diskManager
:
disk
,
source
:
source
,
source
:
source
,
gameWindow
:
gameWindow
,
createPlayer
:
createGame
,
createPlayer
:
createGame
,
fetchBlockNumber
:
fetchBlockNumber
,
fetchBlockNumber
:
fetchBlockNumber
,
allowedGames
:
allowedGames
,
allowedGames
:
allowedGames
,
...
@@ -57,26 +75,59 @@ func (m *gameMonitor) allowedGame(game common.Address) bool {
...
@@ -57,26 +75,59 @@ func (m *gameMonitor) allowedGame(game common.Address) bool {
return
false
return
false
}
}
func
(
m
*
gameMonitor
)
minGameTimestamp
()
uint64
{
if
m
.
gameWindow
.
Seconds
()
==
0
{
return
0
}
// time: "To compute t-d for a duration d, use t.Add(-d)."
// https://pkg.go.dev/time#Time.Sub
if
m
.
clock
.
Now
()
.
Unix
()
>
int64
(
m
.
gameWindow
.
Seconds
())
{
return
uint64
(
m
.
clock
.
Now
()
.
Add
(
-
m
.
gameWindow
)
.
Unix
())
}
return
0
}
func
(
m
*
gameMonitor
)
progressGames
(
ctx
context
.
Context
)
error
{
func
(
m
*
gameMonitor
)
progressGames
(
ctx
context
.
Context
)
error
{
blockNum
,
err
:=
m
.
fetchBlockNumber
(
ctx
)
blockNum
,
err
:=
m
.
fetchBlockNumber
(
ctx
)
if
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to load current block number: %w"
,
err
)
return
fmt
.
Errorf
(
"failed to load current block number: %w"
,
err
)
}
}
games
,
err
:=
m
.
source
.
FetchAllGamesAtBlock
(
ctx
,
new
(
big
.
Int
)
.
SetUint64
(
blockNum
))
games
,
err
:=
m
.
source
.
FetchAllGamesAtBlock
(
ctx
,
m
.
minGameTimestamp
(),
new
(
big
.
Int
)
.
SetUint64
(
blockNum
))
if
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to load games: %w"
,
err
)
return
fmt
.
Errorf
(
"failed to load games: %w"
,
err
)
}
}
requiredGames
:=
make
(
map
[
common
.
Address
]
bool
)
var
keepGameData
[]
common
.
Address
for
_
,
game
:=
range
games
{
for
_
,
game
:=
range
games
{
if
!
m
.
allowedGame
(
game
.
Proxy
)
{
if
!
m
.
allowedGame
(
game
.
Proxy
)
{
m
.
logger
.
Debug
(
"Skipping game not on allow list"
,
"game"
,
game
.
Proxy
)
m
.
logger
.
Debug
(
"Skipping game not on allow list"
,
"game"
,
game
.
Proxy
)
continue
continue
}
}
requiredGames
[
game
.
Proxy
]
=
true
player
,
err
:=
m
.
fetchOrCreateGamePlayer
(
game
)
player
,
err
:=
m
.
fetchOrCreateGamePlayer
(
game
)
if
err
!=
nil
{
if
err
!=
nil
{
m
.
logger
.
Error
(
"Error while progressing game"
,
"game"
,
game
.
Proxy
,
"err"
,
err
)
m
.
logger
.
Error
(
"Error while progressing game"
,
"game"
,
game
.
Proxy
,
"err"
,
err
)
continue
continue
}
}
player
.
ProgressGame
(
ctx
)
done
:=
player
.
ProgressGame
(
ctx
)
if
!
done
{
// We only keep resources on disk for games that are incomplete.
// Games that are complete have their data removed as soon as possible to save disk space.
// We keep the player in memory to avoid recreating it on every update but will no longer
// need the resources on disk because there are no further actions required on the game.
keepGameData
=
append
(
keepGameData
,
game
.
Proxy
)
}
}
if
err
:=
m
.
diskManager
.
RemoveAllExcept
(
keepGameData
);
err
!=
nil
{
m
.
logger
.
Error
(
"Unable to cleanup game data"
,
"err"
,
err
)
}
// Remove the player for any game that's no longer being returned from the list of active games
for
addr
:=
range
m
.
players
{
if
_
,
ok
:=
requiredGames
[
addr
];
ok
{
// Game still required
continue
}
delete
(
m
.
players
,
addr
)
}
}
return
nil
return
nil
}
}
...
@@ -85,7 +136,7 @@ func (m *gameMonitor) fetchOrCreateGamePlayer(gameData FaultDisputeGame) (gamePl
...
@@ -85,7 +136,7 @@ func (m *gameMonitor) fetchOrCreateGamePlayer(gameData FaultDisputeGame) (gamePl
if
player
,
ok
:=
m
.
players
[
gameData
.
Proxy
];
ok
{
if
player
,
ok
:=
m
.
players
[
gameData
.
Proxy
];
ok
{
return
player
,
nil
return
player
,
nil
}
}
player
,
err
:=
m
.
createPlayer
(
gameData
.
Proxy
)
player
,
err
:=
m
.
createPlayer
(
gameData
.
Proxy
,
m
.
diskManager
.
DirForGame
(
gameData
.
Proxy
)
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to create game player %v: %w"
,
gameData
.
Proxy
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to create game player %v: %w"
,
gameData
.
Proxy
,
err
)
}
}
...
...
op-challenger/fault/monitor_test.go
View file @
a382b9e2
...
@@ -4,17 +4,45 @@ import (
...
@@ -4,17 +4,45 @@ import (
"context"
"context"
"math/big"
"math/big"
"testing"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
"golang.org/x/exp/slices"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-node/testlog"
)
)
func
TestMonitorMinGameTimestamp
(
t
*
testing
.
T
)
{
t
.
Parallel
()
t
.
Run
(
"zero game window returns zero"
,
func
(
t
*
testing
.
T
)
{
monitor
,
_
,
_
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
monitor
.
gameWindow
=
time
.
Duration
(
0
)
require
.
Equal
(
t
,
monitor
.
minGameTimestamp
(),
uint64
(
0
))
})
t
.
Run
(
"non-zero game window with zero clock"
,
func
(
t
*
testing
.
T
)
{
monitor
,
_
,
_
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
monitor
.
gameWindow
=
time
.
Minute
monitor
.
clock
=
clock
.
NewDeterministicClock
(
time
.
Unix
(
0
,
0
))
require
.
Equal
(
t
,
monitor
.
minGameTimestamp
(),
uint64
(
0
))
})
t
.
Run
(
"minimum computed correctly"
,
func
(
t
*
testing
.
T
)
{
monitor
,
_
,
_
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
monitor
.
gameWindow
=
time
.
Minute
frozen
:=
time
.
Unix
(
int64
(
time
.
Hour
.
Seconds
()),
0
)
monitor
.
clock
=
clock
.
NewDeterministicClock
(
frozen
)
expected
:=
uint64
(
frozen
.
Add
(
-
time
.
Minute
)
.
Unix
())
require
.
Equal
(
t
,
monitor
.
minGameTimestamp
(),
expected
)
})
}
func
TestMonitorExitsWhenContextDone
(
t
*
testing
.
T
)
{
func
TestMonitorExitsWhenContextDone
(
t
*
testing
.
T
)
{
monitor
,
_
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{
common
.
Address
{}})
monitor
,
_
,
_
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{
{}})
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
cancel
()
cancel
()
err
:=
monitor
.
MonitorGames
(
ctx
)
err
:=
monitor
.
MonitorGames
(
ctx
)
...
@@ -22,7 +50,7 @@ func TestMonitorExitsWhenContextDone(t *testing.T) {
...
@@ -22,7 +50,7 @@ func TestMonitorExitsWhenContextDone(t *testing.T) {
}
}
func
TestMonitorCreateAndProgressGameAgents
(
t
*
testing
.
T
)
{
func
TestMonitorCreateAndProgressGameAgents
(
t
*
testing
.
T
)
{
monitor
,
source
,
games
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
monitor
,
source
,
games
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
addr1
:=
common
.
Address
{
0xaa
}
addr1
:=
common
.
Address
{
0xaa
}
addr2
:=
common
.
Address
{
0xbb
}
addr2
:=
common
.
Address
{
0xbb
}
...
@@ -55,7 +83,7 @@ func TestMonitorCreateAndProgressGameAgents(t *testing.T) {
...
@@ -55,7 +83,7 @@ func TestMonitorCreateAndProgressGameAgents(t *testing.T) {
func
TestMonitorOnlyCreateSpecifiedGame
(
t
*
testing
.
T
)
{
func
TestMonitorOnlyCreateSpecifiedGame
(
t
*
testing
.
T
)
{
addr1
:=
common
.
Address
{
0xaa
}
addr1
:=
common
.
Address
{
0xaa
}
addr2
:=
common
.
Address
{
0xbb
}
addr2
:=
common
.
Address
{
0xbb
}
monitor
,
source
,
games
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{
addr2
})
monitor
,
source
,
games
,
_
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{
addr2
})
source
.
games
=
[]
FaultDisputeGame
{
source
.
games
=
[]
FaultDisputeGame
{
{
{
...
@@ -77,7 +105,82 @@ func TestMonitorOnlyCreateSpecifiedGame(t *testing.T) {
...
@@ -77,7 +105,82 @@ func TestMonitorOnlyCreateSpecifiedGame(t *testing.T) {
require
.
Equal
(
t
,
1
,
games
.
created
[
addr2
]
.
progressCount
)
require
.
Equal
(
t
,
1
,
games
.
created
[
addr2
]
.
progressCount
)
}
}
func
setupMonitorTest
(
t
*
testing
.
T
,
allowedGames
[]
common
.
Address
)
(
*
gameMonitor
,
*
stubGameSource
,
*
createdGames
)
{
func
TestDeletePlayersWhenNoLongerInListOfGames
(
t
*
testing
.
T
)
{
addr1
:=
common
.
Address
{
0xaa
}
addr2
:=
common
.
Address
{
0xbb
}
monitor
,
source
,
games
,
_
:=
setupMonitorTest
(
t
,
nil
)
allGames
:=
[]
FaultDisputeGame
{
{
Proxy
:
addr1
,
Timestamp
:
9999
,
},
{
Proxy
:
addr2
,
Timestamp
:
9999
,
},
}
source
.
games
=
allGames
require
.
NoError
(
t
,
monitor
.
progressGames
(
context
.
Background
()))
require
.
Len
(
t
,
games
.
created
,
2
)
require
.
Contains
(
t
,
games
.
created
,
addr1
)
require
.
Contains
(
t
,
games
.
created
,
addr2
)
// First game is now old enough it's not returned in the list of active games
source
.
games
=
source
.
games
[
1
:
]
require
.
NoError
(
t
,
monitor
.
progressGames
(
context
.
Background
()))
require
.
Len
(
t
,
games
.
created
,
2
)
require
.
Contains
(
t
,
games
.
created
,
addr1
)
require
.
Contains
(
t
,
games
.
created
,
addr2
)
// Forget that we created the first game so it can be recreated if needed
delete
(
games
.
created
,
addr1
)
// First game now reappears (inexplicably but usefully for our testing)
source
.
games
=
allGames
require
.
NoError
(
t
,
monitor
.
progressGames
(
context
.
Background
()))
// A new player is created for it because the original was deleted
require
.
Len
(
t
,
games
.
created
,
2
)
require
.
Contains
(
t
,
games
.
created
,
addr1
)
require
.
Contains
(
t
,
games
.
created
,
addr2
)
require
.
Equal
(
t
,
1
,
games
.
created
[
addr1
]
.
progressCount
)
}
func
TestCleanupResourcesOfCompletedGames
(
t
*
testing
.
T
)
{
addr1
:=
common
.
Address
{
0xaa
}
addr2
:=
common
.
Address
{
0xbb
}
monitor
,
source
,
games
,
disk
:=
setupMonitorTest
(
t
,
[]
common
.
Address
{})
games
.
createCompleted
=
addr1
source
.
games
=
[]
FaultDisputeGame
{
{
Proxy
:
addr1
,
Timestamp
:
1999
,
},
{
Proxy
:
addr2
,
Timestamp
:
9999
,
},
}
err
:=
monitor
.
progressGames
(
context
.
Background
())
require
.
NoError
(
t
,
err
)
require
.
Len
(
t
,
games
.
created
,
2
,
"should create game agents"
)
require
.
Contains
(
t
,
games
.
created
,
addr1
)
require
.
Contains
(
t
,
games
.
created
,
addr2
)
require
.
Equal
(
t
,
1
,
games
.
created
[
addr1
]
.
progressCount
)
require
.
Equal
(
t
,
1
,
games
.
created
[
addr2
]
.
progressCount
)
require
.
Contains
(
t
,
disk
.
gameDirExists
,
addr1
,
"should have allocated a game dir for game 1"
)
require
.
False
(
t
,
disk
.
gameDirExists
[
addr1
],
"should have then deleted the game 1 dir"
)
require
.
Contains
(
t
,
disk
.
gameDirExists
,
addr2
,
"should have allocated a game dir for game 2"
)
require
.
True
(
t
,
disk
.
gameDirExists
[
addr2
],
"should not have deleted the game 2 dir"
)
}
func
setupMonitorTest
(
t
*
testing
.
T
,
allowedGames
[]
common
.
Address
)
(
*
gameMonitor
,
*
stubGameSource
,
*
createdGames
,
*
stubDiskManager
)
{
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlDebug
)
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlDebug
)
source
:=
&
stubGameSource
{}
source
:=
&
stubGameSource
{}
games
:=
&
createdGames
{
games
:=
&
createdGames
{
...
@@ -87,15 +190,18 @@ func setupMonitorTest(t *testing.T, allowedGames []common.Address) (*gameMonitor
...
@@ -87,15 +190,18 @@ func setupMonitorTest(t *testing.T, allowedGames []common.Address) (*gameMonitor
fetchBlockNum
:=
func
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
fetchBlockNum
:=
func
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
return
1234
,
nil
return
1234
,
nil
}
}
monitor
:=
newGameMonitor
(
logger
,
clock
.
SystemClock
,
fetchBlockNum
,
allowedGames
,
source
,
games
.
CreateGame
)
disk
:=
&
stubDiskManager
{
return
monitor
,
source
,
games
gameDirExists
:
make
(
map
[
common
.
Address
]
bool
),
}
monitor
:=
newGameMonitor
(
logger
,
time
.
Duration
(
0
),
clock
.
SystemClock
,
disk
,
fetchBlockNum
,
allowedGames
,
source
,
games
.
CreateGame
)
return
monitor
,
source
,
games
,
disk
}
}
type
stubGameSource
struct
{
type
stubGameSource
struct
{
games
[]
FaultDisputeGame
games
[]
FaultDisputeGame
}
}
func
(
s
*
stubGameSource
)
FetchAllGamesAtBlock
(
ctx
context
.
Context
,
blockNumber
*
big
.
Int
)
([]
FaultDisputeGame
,
error
)
{
func
(
s
*
stubGameSource
)
FetchAllGamesAtBlock
(
ctx
context
.
Context
,
earliest
uint64
,
blockNumber
*
big
.
Int
)
([]
FaultDisputeGame
,
error
)
{
return
s
.
games
,
nil
return
s
.
games
,
nil
}
}
...
@@ -103,6 +209,7 @@ type stubGame struct {
...
@@ -103,6 +209,7 @@ type stubGame struct {
addr
common
.
Address
addr
common
.
Address
progressCount
int
progressCount
int
done
bool
done
bool
dir
string
}
}
func
(
g
*
stubGame
)
ProgressGame
(
ctx
context
.
Context
)
bool
{
func
(
g
*
stubGame
)
ProgressGame
(
ctx
context
.
Context
)
bool
{
...
@@ -111,15 +218,36 @@ func (g *stubGame) ProgressGame(ctx context.Context) bool {
...
@@ -111,15 +218,36 @@ func (g *stubGame) ProgressGame(ctx context.Context) bool {
}
}
type
createdGames
struct
{
type
createdGames
struct
{
t
*
testing
.
T
t
*
testing
.
T
created
map
[
common
.
Address
]
*
stubGame
createCompleted
common
.
Address
created
map
[
common
.
Address
]
*
stubGame
}
}
func
(
c
*
createdGames
)
CreateGame
(
addr
common
.
Address
)
(
gamePlayer
,
error
)
{
func
(
c
*
createdGames
)
CreateGame
(
addr
common
.
Address
,
dir
string
)
(
gamePlayer
,
error
)
{
if
_
,
exists
:=
c
.
created
[
addr
];
exists
{
if
_
,
exists
:=
c
.
created
[
addr
];
exists
{
c
.
t
.
Fatalf
(
"game %v already exists"
,
addr
)
c
.
t
.
Fatalf
(
"game %v already exists"
,
addr
)
}
}
game
:=
&
stubGame
{
addr
:
addr
}
game
:=
&
stubGame
{
addr
:
addr
,
done
:
addr
==
c
.
createCompleted
,
dir
:
dir
,
}
c
.
created
[
addr
]
=
game
c
.
created
[
addr
]
=
game
return
game
,
nil
return
game
,
nil
}
}
type
stubDiskManager
struct
{
gameDirExists
map
[
common
.
Address
]
bool
}
func
(
s
*
stubDiskManager
)
DirForGame
(
addr
common
.
Address
)
string
{
s
.
gameDirExists
[
addr
]
=
true
return
addr
.
Hex
()
}
func
(
s
*
stubDiskManager
)
RemoveAllExcept
(
addrs
[]
common
.
Address
)
error
{
for
address
:=
range
s
.
gameDirExists
{
s
.
gameDirExists
[
address
]
=
slices
.
Contains
(
addrs
,
address
)
}
return
nil
}
op-challenger/fault/player.go
View file @
a382b9e2
...
@@ -10,8 +10,8 @@ import (
...
@@ -10,8 +10,8 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/fault/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/fault/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
)
)
...
@@ -29,15 +29,18 @@ type GamePlayer struct {
...
@@ -29,15 +29,18 @@ type GamePlayer struct {
agreeWithProposedOutput
bool
agreeWithProposedOutput
bool
caller
GameInfo
caller
GameInfo
logger
log
.
Logger
logger
log
.
Logger
completed
bool
}
}
func
NewGamePlayer
(
func
NewGamePlayer
(
ctx
context
.
Context
,
ctx
context
.
Context
,
logger
log
.
Logger
,
logger
log
.
Logger
,
cfg
*
config
.
Config
,
cfg
*
config
.
Config
,
dir
string
,
addr
common
.
Address
,
addr
common
.
Address
,
txMgr
txmgr
.
TxManager
,
txMgr
txmgr
.
TxManager
,
client
*
ethclient
.
Client
,
client
bind
.
ContractCaller
,
)
(
*
GamePlayer
,
error
)
{
)
(
*
GamePlayer
,
error
)
{
logger
=
logger
.
New
(
"game"
,
addr
)
logger
=
logger
.
New
(
"game"
,
addr
)
contract
,
err
:=
bindings
.
NewFaultDisputeGameCaller
(
addr
,
client
)
contract
,
err
:=
bindings
.
NewFaultDisputeGameCaller
(
addr
,
client
)
...
@@ -56,10 +59,11 @@ func NewGamePlayer(
...
@@ -56,10 +59,11 @@ func NewGamePlayer(
var
updater
types
.
OracleUpdater
var
updater
types
.
OracleUpdater
switch
cfg
.
TraceType
{
switch
cfg
.
TraceType
{
case
config
.
TraceTypeCannon
:
case
config
.
TraceTypeCannon
:
provider
,
err
=
cannon
.
NewTraceProvider
(
ctx
,
logger
,
cfg
,
client
,
addr
)
cannonProvider
,
err
:=
cannon
.
NewTraceProvider
(
ctx
,
logger
,
cfg
,
client
,
dir
,
addr
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"create cannon trace provider: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"create cannon trace provider: %w"
,
err
)
}
}
provider
=
cannonProvider
updater
,
err
=
cannon
.
NewOracleUpdater
(
ctx
,
logger
,
txMgr
,
addr
,
client
)
updater
,
err
=
cannon
.
NewOracleUpdater
(
ctx
,
logger
,
txMgr
,
addr
,
client
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to create the cannon updater: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to create the cannon updater: %w"
,
err
)
...
@@ -94,6 +98,11 @@ func NewGamePlayer(
...
@@ -94,6 +98,11 @@ func NewGamePlayer(
}
}
func
(
g
*
GamePlayer
)
ProgressGame
(
ctx
context
.
Context
)
bool
{
func
(
g
*
GamePlayer
)
ProgressGame
(
ctx
context
.
Context
)
bool
{
if
g
.
completed
{
// Game is already complete so don't try to perform further actions.
g
.
logger
.
Trace
(
"Skipping completed game"
)
return
true
}
g
.
logger
.
Trace
(
"Checking if actions are required"
)
g
.
logger
.
Trace
(
"Checking if actions are required"
)
if
err
:=
g
.
agent
.
Act
(
ctx
);
err
!=
nil
{
if
err
:=
g
.
agent
.
Act
(
ctx
);
err
!=
nil
{
g
.
logger
.
Error
(
"Error when acting on game"
,
"err"
,
err
)
g
.
logger
.
Error
(
"Error when acting on game"
,
"err"
,
err
)
...
@@ -102,7 +111,8 @@ func (g *GamePlayer) ProgressGame(ctx context.Context) bool {
...
@@ -102,7 +111,8 @@ func (g *GamePlayer) ProgressGame(ctx context.Context) bool {
g
.
logger
.
Warn
(
"Unable to retrieve game status"
,
"err"
,
err
)
g
.
logger
.
Warn
(
"Unable to retrieve game status"
,
"err"
,
err
)
}
else
{
}
else
{
g
.
logGameStatus
(
ctx
,
status
)
g
.
logGameStatus
(
ctx
,
status
)
return
status
!=
types
.
GameStatusInProgress
g
.
completed
=
status
!=
types
.
GameStatusInProgress
return
g
.
completed
}
}
return
false
return
false
}
}
...
...
op-challenger/fault/player_test.go
View file @
a382b9e2
...
@@ -12,14 +12,14 @@ import (
...
@@ -12,14 +12,14 @@ import (
)
)
func
TestProgressGame_LogErrorFromAct
(
t
*
testing
.
T
)
{
func
TestProgressGame_LogErrorFromAct
(
t
*
testing
.
T
)
{
handler
,
game
,
actor
,
_
:=
setupProgressGameTest
(
t
,
true
)
handler
,
game
,
actor
:=
setupProgressGameTest
(
t
,
true
)
actor
.
e
rr
=
errors
.
New
(
"boom"
)
actor
.
actE
rr
=
errors
.
New
(
"boom"
)
done
:=
game
.
ProgressGame
(
context
.
Background
())
done
:=
game
.
ProgressGame
(
context
.
Background
())
require
.
False
(
t
,
done
,
"should not be done"
)
require
.
False
(
t
,
done
,
"should not be done"
)
require
.
Equal
(
t
,
1
,
actor
.
callCount
,
"should perform next actions"
)
require
.
Equal
(
t
,
1
,
actor
.
callCount
,
"should perform next actions"
)
errLog
:=
handler
.
FindLog
(
log
.
LvlError
,
"Error when acting on game"
)
errLog
:=
handler
.
FindLog
(
log
.
LvlError
,
"Error when acting on game"
)
require
.
NotNil
(
t
,
errLog
,
"should log error"
)
require
.
NotNil
(
t
,
errLog
,
"should log error"
)
require
.
Equal
(
t
,
actor
.
e
rr
,
errLog
.
GetContextValue
(
"err"
))
require
.
Equal
(
t
,
actor
.
actE
rr
,
errLog
.
GetContextValue
(
"err"
))
// Should still log game status
// Should still log game status
msg
:=
handler
.
FindLog
(
log
.
LvlInfo
,
"Game info"
)
msg
:=
handler
.
FindLog
(
log
.
LvlInfo
,
"Game info"
)
...
@@ -74,11 +74,11 @@ func TestProgressGame_LogGameStatus(t *testing.T) {
...
@@ -74,11 +74,11 @@ func TestProgressGame_LogGameStatus(t *testing.T) {
for
_
,
test
:=
range
tests
{
for
_
,
test
:=
range
tests
{
test
:=
test
test
:=
test
t
.
Run
(
test
.
name
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
test
.
name
,
func
(
t
*
testing
.
T
)
{
handler
,
game
,
actor
,
gameInfo
:=
setupProgressGameTest
(
t
,
test
.
agreeWithOutput
)
handler
,
game
,
gameState
:=
setupProgressGameTest
(
t
,
test
.
agreeWithOutput
)
game
Info
.
status
=
test
.
status
game
State
.
status
=
test
.
status
done
:=
game
.
ProgressGame
(
context
.
Background
())
done
:=
game
.
ProgressGame
(
context
.
Background
())
require
.
Equal
(
t
,
1
,
actor
.
callCount
,
"should perform next actions"
)
require
.
Equal
(
t
,
1
,
gameState
.
callCount
,
"should perform next actions"
)
require
.
Equal
(
t
,
test
.
status
!=
types
.
GameStatusInProgress
,
done
,
"should be done when not in progress"
)
require
.
Equal
(
t
,
test
.
status
!=
types
.
GameStatusInProgress
,
done
,
"should be done when not in progress"
)
errLog
:=
handler
.
FindLog
(
test
.
logLevel
,
test
.
logMsg
)
errLog
:=
handler
.
FindLog
(
test
.
logLevel
,
test
.
logMsg
)
require
.
NotNil
(
t
,
errLog
,
"should log game result"
)
require
.
NotNil
(
t
,
errLog
,
"should log game result"
)
...
@@ -87,43 +87,57 @@ func TestProgressGame_LogGameStatus(t *testing.T) {
...
@@ -87,43 +87,57 @@ func TestProgressGame_LogGameStatus(t *testing.T) {
}
}
}
}
func
setupProgressGameTest
(
t
*
testing
.
T
,
agreeWithProposedRoot
bool
)
(
*
testlog
.
CapturingHandler
,
*
GamePlayer
,
*
stubActor
,
*
stubGameInfo
)
{
func
TestDoNotActOnCompleteGame
(
t
*
testing
.
T
)
{
for
_
,
status
:=
range
[]
types
.
GameStatus
{
types
.
GameStatusChallengerWon
,
types
.
GameStatusDefenderWon
}
{
t
.
Run
(
status
.
String
(),
func
(
t
*
testing
.
T
)
{
_
,
game
,
gameState
:=
setupProgressGameTest
(
t
,
true
)
gameState
.
status
=
status
done
:=
game
.
ProgressGame
(
context
.
Background
())
require
.
Equal
(
t
,
1
,
gameState
.
callCount
,
"acts the first time"
)
require
.
True
(
t
,
done
,
"should be done"
)
// Should not act when it knows the game is already complete
done
=
game
.
ProgressGame
(
context
.
Background
())
require
.
Equal
(
t
,
1
,
gameState
.
callCount
,
"does not act after game is complete"
)
require
.
True
(
t
,
done
,
"should still be done"
)
})
}
}
func
setupProgressGameTest
(
t
*
testing
.
T
,
agreeWithProposedRoot
bool
)
(
*
testlog
.
CapturingHandler
,
*
GamePlayer
,
*
stubGameState
)
{
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlDebug
)
logger
:=
testlog
.
Logger
(
t
,
log
.
LvlDebug
)
handler
:=
&
testlog
.
CapturingHandler
{
handler
:=
&
testlog
.
CapturingHandler
{
Delegate
:
logger
.
GetHandler
(),
Delegate
:
logger
.
GetHandler
(),
}
}
logger
.
SetHandler
(
handler
)
logger
.
SetHandler
(
handler
)
actor
:=
&
stubActor
{}
gameState
:=
&
stubGameState
{
claimCount
:
1
}
gameInfo
:=
&
stubGameInfo
{
claimCount
:
1
}
game
:=
&
GamePlayer
{
game
:=
&
GamePlayer
{
agent
:
actor
,
agent
:
gameState
,
agreeWithProposedOutput
:
agreeWithProposedRoot
,
agreeWithProposedOutput
:
agreeWithProposedRoot
,
caller
:
game
Info
,
caller
:
game
State
,
logger
:
logger
,
logger
:
logger
,
}
}
return
handler
,
game
,
actor
,
gameInfo
return
handler
,
game
,
gameState
}
}
type
stubActor
struct
{
type
stubGameState
struct
{
callCount
int
err
error
}
func
(
a
*
stubActor
)
Act
(
ctx
context
.
Context
)
error
{
a
.
callCount
++
return
a
.
err
}
type
stubGameInfo
struct
{
status
types
.
GameStatus
status
types
.
GameStatus
claimCount
uint64
claimCount
uint64
err
error
callCount
int
actErr
error
Err
error
}
func
(
s
*
stubGameState
)
Act
(
ctx
context
.
Context
)
error
{
s
.
callCount
++
return
s
.
actErr
}
}
func
(
s
*
stubGame
Info
)
GetGameStatus
(
ctx
context
.
Context
)
(
types
.
GameStatus
,
error
)
{
func
(
s
*
stubGame
State
)
GetGameStatus
(
ctx
context
.
Context
)
(
types
.
GameStatus
,
error
)
{
return
s
.
status
,
s
.
err
return
s
.
status
,
nil
}
}
func
(
s
*
stubGame
Info
)
GetClaimCount
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
func
(
s
*
stubGame
State
)
GetClaimCount
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
return
s
.
claimCount
,
s
.
err
return
s
.
claimCount
,
nil
}
}
op-challenger/fault/responder.go
View file @
a382b9e2
...
@@ -79,18 +79,25 @@ func (r *faultResponder) BuildTx(ctx context.Context, response types.Claim) ([]b
...
@@ -79,18 +79,25 @@ func (r *faultResponder) BuildTx(ctx context.Context, response types.Claim) ([]b
}
}
}
}
// Ca
n
Resolve determines if the resolve function on the fault dispute game contract
// Ca
ll
Resolve determines if the resolve function on the fault dispute game contract
// would succeed. Returns t
rue if the game can be resolved, otherwise fal
se.
// would succeed. Returns t
he game status if the call would succeed, errors otherwi
se.
func
(
r
*
faultResponder
)
Ca
nResolve
(
ctx
context
.
Context
)
bool
{
func
(
r
*
faultResponder
)
Ca
llResolve
(
ctx
context
.
Context
)
(
types
.
GameStatus
,
error
)
{
txData
,
err
:=
r
.
buildResolveData
()
txData
,
err
:=
r
.
buildResolveData
()
if
err
!=
nil
{
if
err
!=
nil
{
return
false
return
types
.
GameStatusInProgress
,
err
}
}
_
,
err
=
r
.
txMgr
.
Call
(
ctx
,
ethereum
.
CallMsg
{
res
,
err
:
=
r
.
txMgr
.
Call
(
ctx
,
ethereum
.
CallMsg
{
To
:
&
r
.
fdgAddr
,
To
:
&
r
.
fdgAddr
,
Data
:
txData
,
Data
:
txData
,
},
nil
)
},
nil
)
return
err
==
nil
if
err
!=
nil
{
return
types
.
GameStatusInProgress
,
err
}
var
status
uint8
if
err
=
r
.
fdgAbi
.
UnpackIntoInterface
(
&
status
,
"resolve"
,
res
);
err
!=
nil
{
return
types
.
GameStatusInProgress
,
err
}
return
types
.
GameStatusFromUint8
(
status
)
}
}
// Resolve executes a resolve transaction to resolve a fault dispute game.
// Resolve executes a resolve transaction to resolve a fault dispute game.
...
...
op-challenger/fault/responder_test.go
View file @
a382b9e2
This diff is collapsed.
Click to expand it.
op-challenger/fault/service.go
View file @
a382b9e2
...
@@ -73,9 +73,18 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se
...
@@ -73,9 +73,18 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se
}
}
loader
:=
NewGameLoader
(
factory
)
loader
:=
NewGameLoader
(
factory
)
monitor
:=
newGameMonitor
(
logger
,
cl
,
client
.
BlockNumber
,
cfg
.
GameAllowlist
,
loader
,
func
(
addr
common
.
Address
)
(
gamePlayer
,
error
)
{
disk
:=
newDiskManager
(
cfg
.
Datadir
)
return
NewGamePlayer
(
ctx
,
logger
,
cfg
,
addr
,
txMgr
,
client
)
monitor
:=
newGameMonitor
(
})
logger
,
cfg
.
GameWindow
,
cl
,
disk
,
client
.
BlockNumber
,
cfg
.
GameAllowlist
,
loader
,
func
(
addr
common
.
Address
,
dir
string
)
(
gamePlayer
,
error
)
{
return
NewGamePlayer
(
ctx
,
logger
,
cfg
,
dir
,
addr
,
txMgr
,
client
)
})
m
.
RecordInfo
(
version
.
SimpleWithMeta
)
m
.
RecordInfo
(
version
.
SimpleWithMeta
)
m
.
RecordUp
()
m
.
RecordUp
()
...
...
op-challenger/fault/types/types.go
View file @
a382b9e2
...
@@ -3,6 +3,7 @@ package types
...
@@ -3,6 +3,7 @@ package types
import
(
import
(
"context"
"context"
"errors"
"errors"
"fmt"
"math/big"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
...
@@ -34,6 +35,14 @@ func (s GameStatus) String() string {
...
@@ -34,6 +35,14 @@ func (s GameStatus) String() string {
}
}
}
}
// GameStatusFromUint8 returns a game status from the uint8 representation.
func
GameStatusFromUint8
(
i
uint8
)
(
GameStatus
,
error
)
{
if
i
>
2
{
return
GameStatus
(
i
),
fmt
.
Errorf
(
"invalid game status: %d"
,
i
)
}
return
GameStatus
(
i
),
nil
}
// PreimageOracleData encapsulates the preimage oracle data
// PreimageOracleData encapsulates the preimage oracle data
// to load into the onchain oracle.
// to load into the onchain oracle.
type
PreimageOracleData
struct
{
type
PreimageOracleData
struct
{
...
...
op-challenger/fault/types/types_test.go
View file @
a382b9e2
package
types
package
types
import
(
import
(
"fmt"
"testing"
"testing"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
)
)
var
validGameStatuses
=
[]
GameStatus
{
GameStatusInProgress
,
GameStatusChallengerWon
,
GameStatusDefenderWon
,
}
func
TestGameStatusFromUint8
(
t
*
testing
.
T
)
{
for
_
,
status
:=
range
validGameStatuses
{
t
.
Run
(
fmt
.
Sprintf
(
"Valid Game Status %v"
,
status
),
func
(
t
*
testing
.
T
)
{
parsed
,
err
:=
GameStatusFromUint8
(
uint8
(
status
))
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
status
,
parsed
)
})
}
t
.
Run
(
"Invalid"
,
func
(
t
*
testing
.
T
)
{
status
,
err
:=
GameStatusFromUint8
(
3
)
require
.
Error
(
t
,
err
)
require
.
Equal
(
t
,
GameStatus
(
3
),
status
)
})
}
func
TestNewPreimageOracleData
(
t
*
testing
.
T
)
{
func
TestNewPreimageOracleData
(
t
*
testing
.
T
)
{
t
.
Run
(
"LocalData"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"LocalData"
,
func
(
t
*
testing
.
T
)
{
data
:=
NewPreimageOracleData
([]
byte
{
1
,
2
,
3
},
[]
byte
{
4
,
5
,
6
},
7
)
data
:=
NewPreimageOracleData
([]
byte
{
1
,
2
,
3
},
[]
byte
{
4
,
5
,
6
},
7
)
...
...
op-challenger/flags/flags.go
View file @
a382b9e2
...
@@ -57,6 +57,11 @@ var (
...
@@ -57,6 +57,11 @@ var (
Usage
:
"Temporary hardcoded flag if we agree or disagree with the proposed output."
,
Usage
:
"Temporary hardcoded flag if we agree or disagree with the proposed output."
,
EnvVars
:
prefixEnvVars
(
"AGREE_WITH_PROPOSED_OUTPUT"
),
EnvVars
:
prefixEnvVars
(
"AGREE_WITH_PROPOSED_OUTPUT"
),
}
}
DatadirFlag
=
&
cli
.
StringFlag
{
Name
:
"datadir"
,
Usage
:
"Directory to store data generated as part of responding to games"
,
EnvVars
:
prefixEnvVars
(
"DATADIR"
),
}
// Optional Flags
// Optional Flags
AlphabetFlag
=
&
cli
.
StringFlag
{
AlphabetFlag
=
&
cli
.
StringFlag
{
Name
:
"alphabet"
,
Name
:
"alphabet"
,
...
@@ -93,11 +98,6 @@ var (
...
@@ -93,11 +98,6 @@ var (
Usage
:
"Path to absolute prestate to use when generating trace data (cannon trace type only)"
,
Usage
:
"Path to absolute prestate to use when generating trace data (cannon trace type only)"
,
EnvVars
:
prefixEnvVars
(
"CANNON_PRESTATE"
),
EnvVars
:
prefixEnvVars
(
"CANNON_PRESTATE"
),
}
}
CannonDatadirFlag
=
&
cli
.
StringFlag
{
Name
:
"cannon-datadir"
,
Usage
:
"Directory to store data generated by cannon (cannon trace type only)"
,
EnvVars
:
prefixEnvVars
(
"CANNON_DATADIR"
),
}
CannonL2Flag
=
&
cli
.
StringFlag
{
CannonL2Flag
=
&
cli
.
StringFlag
{
Name
:
"cannon-l2"
,
Name
:
"cannon-l2"
,
Usage
:
"L2 Address of L2 JSON-RPC endpoint to use (eth and debug namespace required) (cannon trace type only)"
,
Usage
:
"L2 Address of L2 JSON-RPC endpoint to use (eth and debug namespace required) (cannon trace type only)"
,
...
@@ -109,6 +109,12 @@ var (
...
@@ -109,6 +109,12 @@ var (
EnvVars
:
prefixEnvVars
(
"CANNON_SNAPSHOT_FREQ"
),
EnvVars
:
prefixEnvVars
(
"CANNON_SNAPSHOT_FREQ"
),
Value
:
config
.
DefaultCannonSnapshotFreq
,
Value
:
config
.
DefaultCannonSnapshotFreq
,
}
}
GameWindowFlag
=
&
cli
.
DurationFlag
{
Name
:
"game-window"
,
Usage
:
"The time window which the challenger will look for games to progress."
,
EnvVars
:
prefixEnvVars
(
"GAME_WINDOW"
),
Value
:
config
.
DefaultGameWindow
,
}
)
)
// requiredFlags are checked by [CheckRequired]
// requiredFlags are checked by [CheckRequired]
...
@@ -117,6 +123,7 @@ var requiredFlags = []cli.Flag{
...
@@ -117,6 +123,7 @@ var requiredFlags = []cli.Flag{
FactoryAddressFlag
,
FactoryAddressFlag
,
TraceTypeFlag
,
TraceTypeFlag
,
AgreeWithProposedOutputFlag
,
AgreeWithProposedOutputFlag
,
DatadirFlag
,
}
}
// optionalFlags is a list of unchecked cli flags
// optionalFlags is a list of unchecked cli flags
...
@@ -129,9 +136,9 @@ var optionalFlags = []cli.Flag{
...
@@ -129,9 +136,9 @@ var optionalFlags = []cli.Flag{
CannonBinFlag
,
CannonBinFlag
,
CannonServerFlag
,
CannonServerFlag
,
CannonPreStateFlag
,
CannonPreStateFlag
,
CannonDatadirFlag
,
CannonL2Flag
,
CannonL2Flag
,
CannonSnapshotFreqFlag
,
CannonSnapshotFreqFlag
,
GameWindowFlag
,
}
}
func
init
()
{
func
init
()
{
...
@@ -174,9 +181,6 @@ func CheckRequired(ctx *cli.Context) error {
...
@@ -174,9 +181,6 @@ func CheckRequired(ctx *cli.Context) error {
if
!
ctx
.
IsSet
(
CannonPreStateFlag
.
Name
)
{
if
!
ctx
.
IsSet
(
CannonPreStateFlag
.
Name
)
{
return
fmt
.
Errorf
(
"flag %s is required"
,
CannonPreStateFlag
.
Name
)
return
fmt
.
Errorf
(
"flag %s is required"
,
CannonPreStateFlag
.
Name
)
}
}
if
!
ctx
.
IsSet
(
CannonDatadirFlag
.
Name
)
{
return
fmt
.
Errorf
(
"flag %s is required"
,
CannonDatadirFlag
.
Name
)
}
if
!
ctx
.
IsSet
(
CannonL2Flag
.
Name
)
{
if
!
ctx
.
IsSet
(
CannonL2Flag
.
Name
)
{
return
fmt
.
Errorf
(
"flag %s is required"
,
CannonL2Flag
.
Name
)
return
fmt
.
Errorf
(
"flag %s is required"
,
CannonL2Flag
.
Name
)
}
}
...
@@ -222,6 +226,7 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
...
@@ -222,6 +226,7 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
TraceType
:
traceTypeFlag
,
TraceType
:
traceTypeFlag
,
GameFactoryAddress
:
gameFactoryAddress
,
GameFactoryAddress
:
gameFactoryAddress
,
GameAllowlist
:
allowedGames
,
GameAllowlist
:
allowedGames
,
GameWindow
:
ctx
.
Duration
(
GameWindowFlag
.
Name
),
AlphabetTrace
:
ctx
.
String
(
AlphabetFlag
.
Name
),
AlphabetTrace
:
ctx
.
String
(
AlphabetFlag
.
Name
),
CannonNetwork
:
ctx
.
String
(
CannonNetworkFlag
.
Name
),
CannonNetwork
:
ctx
.
String
(
CannonNetworkFlag
.
Name
),
CannonRollupConfigPath
:
ctx
.
String
(
CannonRollupConfigFlag
.
Name
),
CannonRollupConfigPath
:
ctx
.
String
(
CannonRollupConfigFlag
.
Name
),
...
@@ -229,7 +234,7 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
...
@@ -229,7 +234,7 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
CannonBin
:
ctx
.
String
(
CannonBinFlag
.
Name
),
CannonBin
:
ctx
.
String
(
CannonBinFlag
.
Name
),
CannonServer
:
ctx
.
String
(
CannonServerFlag
.
Name
),
CannonServer
:
ctx
.
String
(
CannonServerFlag
.
Name
),
CannonAbsolutePreState
:
ctx
.
String
(
CannonPreStateFlag
.
Name
),
CannonAbsolutePreState
:
ctx
.
String
(
CannonPreStateFlag
.
Name
),
CannonDatadir
:
ctx
.
String
(
Cannon
DatadirFlag
.
Name
),
Datadir
:
ctx
.
String
(
DatadirFlag
.
Name
),
CannonL2
:
ctx
.
String
(
CannonL2Flag
.
Name
),
CannonL2
:
ctx
.
String
(
CannonL2Flag
.
Name
),
CannonSnapshotFreq
:
ctx
.
Uint
(
CannonSnapshotFreqFlag
.
Name
),
CannonSnapshotFreq
:
ctx
.
Uint
(
CannonSnapshotFreqFlag
.
Name
),
AgreeWithProposedOutput
:
ctx
.
Bool
(
AgreeWithProposedOutputFlag
.
Name
),
AgreeWithProposedOutput
:
ctx
.
Bool
(
AgreeWithProposedOutputFlag
.
Name
),
...
...
op-challenger/scripts/alphabet/charlie.sh
View file @
a382b9e2
...
@@ -19,12 +19,19 @@ DISPUTE_GAME_PROXY=$(jq -r .DisputeGameFactoryProxy $MONOREPO_DIR/.devnet/addres
...
@@ -19,12 +19,19 @@ DISPUTE_GAME_PROXY=$(jq -r .DisputeGameFactoryProxy $MONOREPO_DIR/.devnet/addres
FAULT_GAME_ADDRESS
=
$(
cat
$FAULT_GAME_ADDR_FILE
)
FAULT_GAME_ADDRESS
=
$(
cat
$FAULT_GAME_ADDR_FILE
)
echo
"Fault dispute game address:
$FAULT_GAME_ADDRESS
"
echo
"Fault dispute game address:
$FAULT_GAME_ADDRESS
"
DATADIR
=
`
mktemp
-d
`
trap
cleanup SIGINT
cleanup
(){
rm
-rf
"
${
DATADIR
}
"
}
$CHALLENGER_DIR
/bin/op-challenger
\
$CHALLENGER_DIR
/bin/op-challenger
\
--l1-eth-rpc
http://localhost:8545
\
--l1-eth-rpc
http://localhost:8545
\
--trace-type
=
"alphabet"
\
--trace-type
=
"alphabet"
\
--alphabet
"abcdefgh"
\
--alphabet
"abcdefgh"
\
--datadir
"
${
DATADIR
}
"
\
--game-factory-address
$DISPUTE_GAME_PROXY
\
--game-factory-address
$DISPUTE_GAME_PROXY
\
--game-a
ddress
$FAULT_GAME_ADDRESS
\
--game-a
llowlist
$FAULT_GAME_ADDRESS
\
--private-key
$CHARLIE_KEY
\
--private-key
$CHARLIE_KEY
\
--num-confirmations
1
\
--num-confirmations
1
\
--metrics
.enabled
--metrics
.port
=
7304
\
--metrics
.enabled
--metrics
.port
=
7304
\
...
...
op-challenger/scripts/alphabet/mallory.sh
View file @
a382b9e2
...
@@ -19,12 +19,19 @@ DISPUTE_GAME_PROXY=$(jq -r .DisputeGameFactoryProxy $MONOREPO_DIR/.devnet/addres
...
@@ -19,12 +19,19 @@ DISPUTE_GAME_PROXY=$(jq -r .DisputeGameFactoryProxy $MONOREPO_DIR/.devnet/addres
FAULT_GAME_ADDRESS
=
$(
cat
$FAULT_GAME_ADDR_FILE
)
FAULT_GAME_ADDRESS
=
$(
cat
$FAULT_GAME_ADDR_FILE
)
echo
"Fault dispute game address:
$FAULT_GAME_ADDRESS
"
echo
"Fault dispute game address:
$FAULT_GAME_ADDRESS
"
DATADIR
=
`
mktemp
-d
`
trap
cleanup SIGINT
cleanup
(){
rm
-rf
"
${
DATADIR
}
"
}
$CHALLENGER_DIR
/bin/op-challenger
\
$CHALLENGER_DIR
/bin/op-challenger
\
--l1-eth-rpc
http://localhost:8545
\
--l1-eth-rpc
http://localhost:8545
\
--trace-type
=
"alphabet"
\
--trace-type
=
"alphabet"
\
--alphabet
"abcdexyz"
\
--alphabet
"abcdexyz"
\
--datadir
"
${
DATADIR
}
"
\
--game-factory-address
$DISPUTE_GAME_PROXY
\
--game-factory-address
$DISPUTE_GAME_PROXY
\
--game-a
ddress
$FAULT_GAME_ADDRESS
\
--game-a
llowlist
$FAULT_GAME_ADDRESS
\
--private-key
$MALLORY_KEY
\
--private-key
$MALLORY_KEY
\
--num-confirmations
1
\
--num-confirmations
1
\
--metrics
.enabled
--metrics
.port
=
7305
\
--metrics
.enabled
--metrics
.port
=
7305
\
...
...
op-e2e/e2eutils/challenger/helper.go
View file @
a382b9e2
...
@@ -23,9 +23,11 @@ import (
...
@@ -23,9 +23,11 @@ import (
)
)
type
Helper
struct
{
type
Helper
struct
{
log
log
.
Logger
log
log
.
Logger
cancel
func
()
require
*
require
.
Assertions
errors
chan
error
dir
string
cancel
func
()
errors
chan
error
}
}
type
Option
func
(
config2
*
config
.
Config
)
type
Option
func
(
config2
*
config
.
Config
)
...
@@ -74,7 +76,6 @@ func WithCannon(
...
@@ -74,7 +76,6 @@ func WithCannon(
require
:=
require
.
New
(
t
)
require
:=
require
.
New
(
t
)
c
.
TraceType
=
config
.
TraceTypeCannon
c
.
TraceType
=
config
.
TraceTypeCannon
c
.
CannonL2
=
l2Endpoint
c
.
CannonL2
=
l2Endpoint
c
.
CannonDatadir
=
t
.
TempDir
()
c
.
CannonBin
=
"../cannon/bin/cannon"
c
.
CannonBin
=
"../cannon/bin/cannon"
c
.
CannonServer
=
"../op-program/bin/op-program"
c
.
CannonServer
=
"../op-program/bin/op-program"
c
.
CannonAbsolutePreState
=
"../op-program/bin/prestate.json"
c
.
CannonAbsolutePreState
=
"../op-program/bin/prestate.json"
...
@@ -82,13 +83,13 @@ func WithCannon(
...
@@ -82,13 +83,13 @@ func WithCannon(
genesisBytes
,
err
:=
json
.
Marshal
(
l2Genesis
)
genesisBytes
,
err
:=
json
.
Marshal
(
l2Genesis
)
require
.
NoError
(
err
,
"marshall l2 genesis config"
)
require
.
NoError
(
err
,
"marshall l2 genesis config"
)
genesisFile
:=
filepath
.
Join
(
c
.
Cannon
Datadir
,
"l2-genesis.json"
)
genesisFile
:=
filepath
.
Join
(
c
.
Datadir
,
"l2-genesis.json"
)
require
.
NoError
(
os
.
WriteFile
(
genesisFile
,
genesisBytes
,
0644
))
require
.
NoError
(
os
.
WriteFile
(
genesisFile
,
genesisBytes
,
0644
))
c
.
CannonL2GenesisPath
=
genesisFile
c
.
CannonL2GenesisPath
=
genesisFile
rollupBytes
,
err
:=
json
.
Marshal
(
rollupCfg
)
rollupBytes
,
err
:=
json
.
Marshal
(
rollupCfg
)
require
.
NoError
(
err
,
"marshall rollup config"
)
require
.
NoError
(
err
,
"marshall rollup config"
)
rollupFile
:=
filepath
.
Join
(
c
.
Cannon
Datadir
,
"rollup.json"
)
rollupFile
:=
filepath
.
Join
(
c
.
Datadir
,
"rollup.json"
)
require
.
NoError
(
os
.
WriteFile
(
rollupFile
,
rollupBytes
,
0644
))
require
.
NoError
(
os
.
WriteFile
(
rollupFile
,
rollupBytes
,
0644
))
c
.
CannonRollupConfigPath
=
rollupFile
c
.
CannonRollupConfigPath
=
rollupFile
}
}
...
@@ -106,9 +107,11 @@ func NewChallenger(t *testing.T, ctx context.Context, l1Endpoint string, name st
...
@@ -106,9 +107,11 @@ func NewChallenger(t *testing.T, ctx context.Context, l1Endpoint string, name st
errCh
<-
op_challenger
.
Main
(
ctx
,
log
,
cfg
)
errCh
<-
op_challenger
.
Main
(
ctx
,
log
,
cfg
)
}()
}()
return
&
Helper
{
return
&
Helper
{
log
:
log
,
log
:
log
,
cancel
:
cancel
,
require
:
require
.
New
(
t
),
errors
:
errCh
,
dir
:
cfg
.
Datadir
,
cancel
:
cancel
,
errors
:
errCh
,
}
}
}
}
...
@@ -121,6 +124,7 @@ func NewChallengerConfig(t *testing.T, l1Endpoint string, options ...Option) *co
...
@@ -121,6 +124,7 @@ func NewChallengerConfig(t *testing.T, l1Endpoint string, options ...Option) *co
AlphabetTrace
:
""
,
AlphabetTrace
:
""
,
AgreeWithProposedOutput
:
true
,
AgreeWithProposedOutput
:
true
,
TxMgrConfig
:
txmgrCfg
,
TxMgrConfig
:
txmgrCfg
,
Datadir
:
t
.
TempDir
(),
}
}
for
_
,
option
:=
range
options
{
for
_
,
option
:=
range
options
{
option
(
cfg
)
option
(
cfg
)
...
@@ -155,3 +159,25 @@ func (h *Helper) Close() error {
...
@@ -155,3 +159,25 @@ func (h *Helper) Close() error {
return
nil
return
nil
}
}
}
}
type
GameAddr
interface
{
Addr
()
common
.
Address
}
func
(
h
*
Helper
)
VerifyGameDataExists
(
games
...
GameAddr
)
{
for
_
,
game
:=
range
games
{
addr
:=
game
.
Addr
()
h
.
require
.
DirExistsf
(
h
.
gameDataDir
(
addr
),
"should have data for game %v"
,
addr
)
}
}
func
(
h
*
Helper
)
VerifyNoGameDataExists
(
games
...
GameAddr
)
{
for
_
,
game
:=
range
games
{
addr
:=
game
.
Addr
()
h
.
require
.
NoDirExistsf
(
h
.
gameDataDir
(
addr
),
"should have data for game %v"
,
addr
)
}
}
func
(
h
*
Helper
)
gameDataDir
(
addr
common
.
Address
)
string
{
return
filepath
.
Join
(
h
.
dir
,
addr
.
Hex
())
}
op-e2e/e2eutils/disputegame/cannon_helper.go
View file @
a382b9e2
...
@@ -2,6 +2,7 @@ package disputegame
...
@@ -2,6 +2,7 @@ package disputegame
import
(
import
(
"context"
"context"
"path/filepath"
"github.com/ethereum-optimism/optimism/op-challenger/fault/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/fault/cannon"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
...
@@ -38,7 +39,8 @@ func (g *CannonGameHelper) CreateHonestActor(ctx context.Context, rollupCfg *rol
...
@@ -38,7 +39,8 @@ func (g *CannonGameHelper) CreateHonestActor(ctx context.Context, rollupCfg *rol
}
}
opts
=
append
(
opts
,
options
...
)
opts
=
append
(
opts
,
options
...
)
cfg
:=
challenger
.
NewChallengerConfig
(
g
.
t
,
l1Endpoint
,
opts
...
)
cfg
:=
challenger
.
NewChallengerConfig
(
g
.
t
,
l1Endpoint
,
opts
...
)
provider
,
err
:=
cannon
.
NewTraceProvider
(
ctx
,
testlog
.
Logger
(
g
.
t
,
log
.
LvlInfo
)
.
New
(
"role"
,
"CorrectTrace"
),
cfg
,
l1Client
,
g
.
addr
)
logger
:=
testlog
.
Logger
(
g
.
t
,
log
.
LvlInfo
)
.
New
(
"role"
,
"CorrectTrace"
)
provider
,
err
:=
cannon
.
NewTraceProvider
(
ctx
,
logger
,
cfg
,
l1Client
,
filepath
.
Join
(
cfg
.
Datadir
,
"honest"
),
g
.
addr
)
g
.
require
.
NoError
(
err
,
"create cannon trace provider"
)
g
.
require
.
NoError
(
err
,
"create cannon trace provider"
)
return
&
HonestHelper
{
return
&
HonestHelper
{
...
...
op-e2e/e2eutils/disputegame/game_helper.go
View file @
a382b9e2
...
@@ -26,6 +26,10 @@ type FaultGameHelper struct {
...
@@ -26,6 +26,10 @@ type FaultGameHelper struct {
addr
common
.
Address
addr
common
.
Address
}
}
func
(
g
*
FaultGameHelper
)
Addr
()
common
.
Address
{
return
g
.
addr
}
func
(
g
*
FaultGameHelper
)
GameDuration
(
ctx
context
.
Context
)
time
.
Duration
{
func
(
g
*
FaultGameHelper
)
GameDuration
(
ctx
context
.
Context
)
time
.
Duration
{
duration
,
err
:=
g
.
game
.
GAMEDURATION
(
&
bind
.
CallOpts
{
Context
:
ctx
})
duration
,
err
:=
g
.
game
.
GAMEDURATION
(
&
bind
.
CallOpts
{
Context
:
ctx
})
g
.
require
.
NoError
(
err
,
"failed to get game duration"
)
g
.
require
.
NoError
(
err
,
"failed to get game duration"
)
...
...
op-e2e/e2eutils/disputegame/helper.go
View file @
a382b9e2
...
@@ -175,7 +175,7 @@ func (h *FactoryHelper) StartCannonGameWithCorrectRoot(ctx context.Context, roll
...
@@ -175,7 +175,7 @@ func (h *FactoryHelper) StartCannonGameWithCorrectRoot(ctx context.Context, roll
L2Claim
:
challengedOutput
.
OutputRoot
,
L2Claim
:
challengedOutput
.
OutputRoot
,
L2BlockNumber
:
challengedOutput
.
L2BlockNumber
,
L2BlockNumber
:
challengedOutput
.
L2BlockNumber
,
}
}
provider
:=
cannon
.
NewTraceProviderFromInputs
(
testlog
.
Logger
(
h
.
t
,
log
.
LvlInfo
)
.
New
(
"role"
,
"CorrectTrace"
),
cfg
,
"correct"
,
inputs
)
provider
:=
cannon
.
NewTraceProviderFromInputs
(
testlog
.
Logger
(
h
.
t
,
log
.
LvlInfo
)
.
New
(
"role"
,
"CorrectTrace"
),
cfg
,
inputs
,
cfg
.
Datadir
)
rootClaim
,
err
:=
provider
.
Get
(
ctx
,
math
.
MaxUint64
)
rootClaim
,
err
:=
provider
.
Get
(
ctx
,
math
.
MaxUint64
)
h
.
require
.
NoError
(
err
,
"Compute correct root hash"
)
h
.
require
.
NoError
(
err
,
"Compute correct root hash"
)
...
...
op-e2e/faultproof_test.go
View file @
a382b9e2
...
@@ -58,7 +58,7 @@ func TestMultipleCannonGames(t *testing.T) {
...
@@ -58,7 +58,7 @@ func TestMultipleCannonGames(t *testing.T) {
gameFactory
:=
disputegame
.
NewFactoryHelper
(
t
,
ctx
,
sys
.
cfg
.
L1Deployments
,
l1Client
)
gameFactory
:=
disputegame
.
NewFactoryHelper
(
t
,
ctx
,
sys
.
cfg
.
L1Deployments
,
l1Client
)
// Start a challenger with the correct alphabet trace
// Start a challenger with the correct alphabet trace
gameFactory
.
StartChallenger
(
ctx
,
sys
.
NodeEndpoint
(
"l1"
),
"TowerDefense"
,
challenger
:=
gameFactory
.
StartChallenger
(
ctx
,
sys
.
NodeEndpoint
(
"l1"
),
"TowerDefense"
,
challenger
.
WithCannon
(
t
,
sys
.
RollupConfig
,
sys
.
L2GenesisCfg
,
sys
.
NodeEndpoint
(
"sequencer"
)),
challenger
.
WithCannon
(
t
,
sys
.
RollupConfig
,
sys
.
L2GenesisCfg
,
sys
.
NodeEndpoint
(
"sequencer"
)),
challenger
.
WithPrivKey
(
sys
.
cfg
.
Secrets
.
Alice
),
challenger
.
WithPrivKey
(
sys
.
cfg
.
Secrets
.
Alice
),
challenger
.
WithAgreeProposedOutput
(
true
),
challenger
.
WithAgreeProposedOutput
(
true
),
...
@@ -74,6 +74,9 @@ func TestMultipleCannonGames(t *testing.T) {
...
@@ -74,6 +74,9 @@ func TestMultipleCannonGames(t *testing.T) {
game2Claim
:=
game2
.
GetClaimValue
(
ctx
,
1
)
game2Claim
:=
game2
.
GetClaimValue
(
ctx
,
1
)
require
.
NotEqual
(
t
,
game1Claim
,
game2Claim
,
"games should have different cannon traces"
)
require
.
NotEqual
(
t
,
game1Claim
,
game2Claim
,
"games should have different cannon traces"
)
// Check that the helper finds the game directories correctly
challenger
.
VerifyGameDataExists
(
game1
,
game2
)
// Push both games down to the step function
// Push both games down to the step function
maxDepth
:=
game1
.
MaxDepth
(
ctx
)
maxDepth
:=
game1
.
MaxDepth
(
ctx
)
for
claimCount
:=
int64
(
1
);
claimCount
<=
maxDepth
;
{
for
claimCount
:=
int64
(
1
);
claimCount
<=
maxDepth
;
{
...
@@ -97,8 +100,9 @@ func TestMultipleCannonGames(t *testing.T) {
...
@@ -97,8 +100,9 @@ func TestMultipleCannonGames(t *testing.T) {
game1
.
WaitForGameStatus
(
ctx
,
disputegame
.
StatusChallengerWins
)
game1
.
WaitForGameStatus
(
ctx
,
disputegame
.
StatusChallengerWins
)
game2
.
WaitForGameStatus
(
ctx
,
disputegame
.
StatusChallengerWins
)
game2
.
WaitForGameStatus
(
ctx
,
disputegame
.
StatusChallengerWins
)
game1
.
LogGameData
(
ctx
)
game2
.
LogGameData
(
ctx
)
// Check that the game directories are removed
challenger
.
VerifyNoGameDataExists
(
game1
,
game2
)
}
}
func
TestResolveDisputeGame
(
t
*
testing
.
T
)
{
func
TestResolveDisputeGame
(
t
*
testing
.
T
)
{
...
...
op-exporter/Dockerfile
View file @
a382b9e2
FROM
golang:1.
19.9-alpine3.16
as builder
FROM
golang:1.
20.7-alpine3.18
as builder
# build from root of repo
# build from root of repo
COPY
./op-exporter /app
COPY
./op-exporter /app
...
@@ -7,7 +7,7 @@ WORKDIR /app/
...
@@ -7,7 +7,7 @@ WORKDIR /app/
RUN
apk
--no-cache
add make bash jq git
RUN
apk
--no-cache
add make bash jq git
RUN
make build
RUN
make build
FROM
alpine:3.1
6
FROM
alpine:3.1
8
RUN
apk
--no-cache
add ca-certificates
RUN
apk
--no-cache
add ca-certificates
WORKDIR
/root/
WORKDIR
/root/
COPY
--from=builder /app/op-exporter /usr/local/bin/
COPY
--from=builder /app/op-exporter /usr/local/bin/
...
...
op-exporter/go.mod
View file @
a382b9e2
module github.com/ethereum-optimism/optimism/op-exporter
module github.com/ethereum-optimism/optimism/op-exporter
go 1.
18
go 1.
20
require (
require (
github.com/ethereum/go-ethereum v1.10.17
github.com/ethereum/go-ethereum v1.10.17
...
...
op-heartbeat/Dockerfile
View file @
a382b9e2
FROM
golang:1.
19.9-alpine3.16
as builder
FROM
golang:1.
20.7-alpine3.18
as builder
RUN
apk add
--no-cache
make gcc musl-dev linux-headers git jq bash
RUN
apk add
--no-cache
make gcc musl-dev linux-headers git jq bash
...
@@ -15,7 +15,7 @@ WORKDIR /app/op-heartbeat
...
@@ -15,7 +15,7 @@ WORKDIR /app/op-heartbeat
RUN
make op-heartbeat
RUN
make op-heartbeat
FROM
alpine:3.1
6
FROM
alpine:3.1
8
COPY
--from=builder /app/op-heartbeat/bin/op-heartbeat /usr/local/bin
COPY
--from=builder /app/op-heartbeat/bin/op-heartbeat /usr/local/bin
...
...
op-node/Dockerfile
View file @
a382b9e2
FROM
--platform=$BUILDPLATFORM golang:1.
19.9-alpine3.16
as builder
FROM
--platform=$BUILDPLATFORM golang:1.
20.7-alpine3.18
as builder
ARG
VERSION=v0.0.0
ARG
VERSION=v0.0.0
...
@@ -21,7 +21,7 @@ ARG TARGETOS TARGETARCH
...
@@ -21,7 +21,7 @@ ARG TARGETOS TARGETARCH
RUN
make op-node
VERSION
=
"
$VERSION
"
GOOS
=
$TARGETOS
GOARCH
=
$TARGETARCH
RUN
make op-node
VERSION
=
"
$VERSION
"
GOOS
=
$TARGETOS
GOARCH
=
$TARGETARCH
FROM
alpine:3.1
6
FROM
alpine:3.1
8
COPY
--from=builder /app/op-node/bin/op-node /usr/local/bin
COPY
--from=builder /app/op-node/bin/op-node /usr/local/bin
...
...
op-node/rollup/derive/l1_block_info_test.go
View file @
a382b9e2
package
derive
package
derive
import
(
import
(
crand
"crypto/rand"
"math/big"
"math/big"
"math/rand"
"math/rand"
"testing"
"testing"
...
@@ -97,7 +98,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) {
...
@@ -97,7 +98,7 @@ func TestParseL1InfoDepositTxData(t *testing.T) {
info
:=
testutils
.
MakeBlockInfo
(
nil
)(
rng
)
info
:=
testutils
.
MakeBlockInfo
(
nil
)(
rng
)
depTx
,
err
:=
L1InfoDeposit
(
randomSeqNr
(
rng
),
info
,
randomL1Cfg
(
rng
,
info
),
false
)
depTx
,
err
:=
L1InfoDeposit
(
randomSeqNr
(
rng
),
info
,
randomL1Cfg
(
rng
,
info
),
false
)
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
_
,
err
=
rand
.
Read
(
depTx
.
Data
[
0
:
4
])
_
,
err
=
c
rand
.
Read
(
depTx
.
Data
[
0
:
4
])
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
_
,
err
=
L1InfoDepositTxData
(
depTx
.
Data
)
_
,
err
=
L1InfoDepositTxData
(
depTx
.
Data
)
require
.
ErrorContains
(
t
,
err
,
"function signature"
)
require
.
ErrorContains
(
t
,
err
,
"function signature"
)
...
...
op-node/sources/eth_client_test.go
View file @
a382b9e2
...
@@ -2,8 +2,8 @@ package sources
...
@@ -2,8 +2,8 @@ package sources
import
(
import
(
"context"
"context"
crand
"crypto/rand"
"math/big"
"math/big"
"math/rand"
"testing"
"testing"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/mock"
...
@@ -56,7 +56,7 @@ var testEthClientConfig = &EthClientConfig{
...
@@ -56,7 +56,7 @@ var testEthClientConfig = &EthClientConfig{
}
}
func
randHash
()
(
out
common
.
Hash
)
{
func
randHash
()
(
out
common
.
Hash
)
{
rand
.
Read
(
out
[
:
])
_
,
_
=
c
rand
.
Read
(
out
[
:
])
return
out
return
out
}
}
...
...
op-program/Dockerfile
View file @
a382b9e2
FROM
--platform=$BUILDPLATFORM golang:1.
19.9-alpine3.16
as builder
FROM
--platform=$BUILDPLATFORM golang:1.
20.7-alpine3.18
as builder
ARG
VERSION=v0.0.0
ARG
VERSION=v0.0.0
...
@@ -23,7 +23,7 @@ ARG TARGETOS TARGETARCH
...
@@ -23,7 +23,7 @@ ARG TARGETOS TARGETARCH
RUN
make op-program
VERSION
=
"
$VERSION
"
GOOS
=
$TARGETOS
GOARCH
=
$TARGETARCH
RUN
make op-program
VERSION
=
"
$VERSION
"
GOOS
=
$TARGETOS
GOARCH
=
$TARGETARCH
FROM
alpine:3.1
6
FROM
alpine:3.1
8
COPY
--from=builder /app/op-program/bin/op-program /usr/local/bin
COPY
--from=builder /app/op-program/bin/op-program /usr/local/bin
...
...
op-proposer/Dockerfile
View file @
a382b9e2
FROM
--platform=$BUILDPLATFORM golang:1.
19.9-alpine3.16
as builder
FROM
--platform=$BUILDPLATFORM golang:1.
20.7-alpine3.18
as builder
ARG
VERSION=v0.0.0
ARG
VERSION=v0.0.0
...
@@ -22,7 +22,7 @@ ARG TARGETOS TARGETARCH
...
@@ -22,7 +22,7 @@ ARG TARGETOS TARGETARCH
RUN
make op-proposer
VERSION
=
"
$VERSION
"
GOOS
=
$TARGETOS
GOARCH
=
$TARGETARCH
RUN
make op-proposer
VERSION
=
"
$VERSION
"
GOOS
=
$TARGETOS
GOARCH
=
$TARGETARCH
FROM
alpine:3.1
6
FROM
alpine:3.1
8
COPY
--from=builder /app/op-proposer/bin/op-proposer /usr/local/bin
COPY
--from=builder /app/op-proposer/bin/op-proposer /usr/local/bin
...
...
op-wheel/Dockerfile
View file @
a382b9e2
FROM
golang:1.
19.9-alpine3.16
as builder
FROM
golang:1.
20.7-alpine3.18
as builder
RUN
apk add
--no-cache
make gcc musl-dev linux-headers
RUN
apk add
--no-cache
make gcc musl-dev linux-headers
...
@@ -14,7 +14,7 @@ WORKDIR /app/op-wheel
...
@@ -14,7 +14,7 @@ WORKDIR /app/op-wheel
RUN
go build
-o
op-wheel ./cmd/main.go
RUN
go build
-o
op-wheel ./cmd/main.go
FROM
alpine:3.1
6
FROM
alpine:3.1
8
COPY
--from=builder /app/op-wheel/op-wheel /usr/local/bin
COPY
--from=builder /app/op-wheel/op-wheel /usr/local/bin
...
...
package.json
View file @
a382b9e2
...
@@ -43,7 +43,7 @@
...
@@ -43,7 +43,7 @@
"
@types/chai
"
:
"
^4.2.18
"
,
"
@types/chai
"
:
"
^4.2.18
"
,
"
@types/chai-as-promised
"
:
"
^7.1.4
"
,
"
@types/chai-as-promised
"
:
"
^7.1.4
"
,
"
@types/mocha
"
:
"
^10.0.1
"
,
"
@types/mocha
"
:
"
^10.0.1
"
,
"
@types/node
"
:
"
^
12.0.0
"
,
"
@types/node
"
:
"
^
20.5.3
"
,
"
@typescript-eslint/eslint-plugin
"
:
"
^5.60.1
"
,
"
@typescript-eslint/eslint-plugin
"
:
"
^5.60.1
"
,
"
@typescript-eslint/parser
"
:
"
^5.60.1
"
,
"
@typescript-eslint/parser
"
:
"
^5.60.1
"
,
"
chai
"
:
"
^4.2.0
"
,
"
chai
"
:
"
^4.2.0
"
,
...
@@ -63,12 +63,12 @@
...
@@ -63,12 +63,12 @@
"
eslint-plugin-unicorn
"
:
"
^42.0.0
"
,
"
eslint-plugin-unicorn
"
:
"
^42.0.0
"
,
"
husky
"
:
"
^8.0.3
"
,
"
husky
"
:
"
^8.0.3
"
,
"
lerna
"
:
"
^7.1.5
"
,
"
lerna
"
:
"
^7.1.5
"
,
"
lint-staged
"
:
"
1
1.0.0
"
,
"
lint-staged
"
:
"
1
4.0.1
"
,
"
markdownlint
"
:
"
^0.24.0
"
,
"
markdownlint
"
:
"
^0.24.0
"
,
"
markdownlint-cli2
"
:
"
0.4.0
"
,
"
markdownlint-cli2
"
:
"
0.4.0
"
,
"
mkdirp
"
:
"
^1.0.4
"
,
"
mkdirp
"
:
"
^1.0.4
"
,
"
mocha
"
:
"
^10.2.0
"
,
"
mocha
"
:
"
^10.2.0
"
,
"
nx
"
:
"
16.7.
2
"
,
"
nx
"
:
"
16.7.
3
"
,
"
nyc
"
:
"
^15.1.0
"
,
"
nyc
"
:
"
^15.1.0
"
,
"
patch-package
"
:
"
^8.0.0
"
,
"
patch-package
"
:
"
^8.0.0
"
,
"
prettier
"
:
"
^2.8.0
"
,
"
prettier
"
:
"
^2.8.0
"
,
...
...
packages/contracts-bedrock/package.json
View file @
a382b9e2
...
@@ -41,7 +41,7 @@
...
@@ -41,7 +41,7 @@
"lint"
:
"pnpm lint:fix && pnpm lint:check"
"lint"
:
"pnpm lint:fix && pnpm lint:check"
},
},
"devDependencies"
:
{
"devDependencies"
:
{
"@typescript-eslint/eslint-plugin"
:
"^
6.4
.0"
,
"@typescript-eslint/eslint-plugin"
:
"^
5.62
.0"
,
"@typescript-eslint/parser"
:
"^6.4.0"
,
"@typescript-eslint/parser"
:
"^6.4.0"
,
"tsx"
:
"^3.12.7"
,
"tsx"
:
"^3.12.7"
,
"typescript"
:
"^5.1.6"
"typescript"
:
"^5.1.6"
...
...
packages/contracts-bedrock/test-case-generator/go.mod
View file @
a382b9e2
module github.com/ethereum-optimism/optimism/packages/contracts-bedrock/ctb-test-case-generator
module github.com/ethereum-optimism/optimism/packages/contracts-bedrock/ctb-test-case-generator
go 1.
19
go 1.
20
require github.com/ethereum/go-ethereum v1.10.26
require github.com/ethereum/go-ethereum v1.10.26
...
...
packages/contracts-ts/package.json
View file @
a382b9e2
...
@@ -48,7 +48,7 @@
...
@@ -48,7 +48,7 @@
},
},
"devDependencies"
:
{
"devDependencies"
:
{
"@eth-optimism/contracts-bedrock"
:
"workspace:*"
,
"@eth-optimism/contracts-bedrock"
:
"workspace:*"
,
"@testing-library/jest-dom"
:
"^
5.17.0
"
,
"@testing-library/jest-dom"
:
"^
6.0.1
"
,
"@testing-library/react-hooks"
:
"^8.0.1"
,
"@testing-library/react-hooks"
:
"^8.0.1"
,
"@types/glob"
:
"^8.1.0"
,
"@types/glob"
:
"^8.1.0"
,
"@vitest/coverage-istanbul"
:
"^0.34.1"
,
"@vitest/coverage-istanbul"
:
"^0.34.1"
,
...
...
packages/fee-estimation/package.json
View file @
a382b9e2
...
@@ -35,7 +35,7 @@
...
@@ -35,7 +35,7 @@
},
},
"devDependencies"
:
{
"devDependencies"
:
{
"@eth-optimism/contracts-ts"
:
"workspace:^"
,
"@eth-optimism/contracts-ts"
:
"workspace:^"
,
"@testing-library/jest-dom"
:
"^
5.17.0
"
,
"@testing-library/jest-dom"
:
"^
6.0.1
"
,
"@testing-library/react-hooks"
:
"^8.0.1"
,
"@testing-library/react-hooks"
:
"^8.0.1"
,
"@vitest/coverage-istanbul"
:
"^0.34.1"
,
"@vitest/coverage-istanbul"
:
"^0.34.1"
,
"abitype"
:
"^0.9.3"
,
"abitype"
:
"^0.9.3"
,
...
...
pnpm-lock.yaml
View file @
a382b9e2
This diff is collapsed.
Click to expand it.
proxyd/go.mod
View file @
a382b9e2
module github.com/ethereum-optimism/optimism/proxyd
module github.com/ethereum-optimism/optimism/proxyd
go 1.
18
go 1.
20
require (
require (
github.com/BurntSushi/toml v1.2.0
github.com/BurntSushi/toml v1.2.0
...
...
specs/meta/devnet.md
View file @
a382b9e2
...
@@ -9,9 +9,9 @@
...
@@ -9,9 +9,9 @@
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
You can spin up a local devnet via
`docker
-
compose`
.
You can spin up a local devnet via
`docker
compose`
.
For convenience, we have defined
`make`
targets to start and stop the devnet with a single command.
For convenience, we have defined
`make`
targets to start and stop the devnet with a single command.
To run the devnet, you will need
`docker`
and
`docker-compose`
installed.
To run the devnet, you will need
`docker`
installed.
Then, as a precondition, make sure that you have compiled the contracts by
`cd`
ing into
`packages/contracts`
Then, as a precondition, make sure that you have compiled the contracts by
`cd`
ing into
`packages/contracts`
and running
`pnpm i`
followed by
`pnpm build`
. You'll only need to do this if you change the contracts in the future.
and running
`pnpm i`
followed by
`pnpm build`
. You'll only need to do this if you change the contracts in the future.
...
...
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