Commit 7c43a6ad authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into willc/release-codeowners

parents b0821fa0 5f3aed08
......@@ -3,7 +3,7 @@
"changelog": ["@changesets/changelog-github", { "repo": "ethereum-optimism/optimism" }],
"commit": false,
"fixed": [],
"linked": [],
"linked": [["@eth-optimism/contracts-bedrock", "@eth-optimism/contracts-ts"]],
"access": "public",
"baseBranch": "develop",
"updateInternalDependencies": "patch",
......
---
'@eth-optimism/sdk': minor
---
Added to and from block filters to several methods in CrossChainMessenger
......@@ -143,6 +143,7 @@ jobs:
- "packages/fault-detector/node_modules"
- "packages/replica-healthcheck/node_modules"
- "packages/sdk/node_modules"
- "packages/contracts-ts/node_modules"
- run:
name: print forge version
command: forge --version
......@@ -196,7 +197,7 @@ jobs:
fi
IMAGE_BASE="<<parameters.registry>>/<<parameters.repo>>/<<parameters.docker_name>>"
DOCKER_TAGS=$(echo -ne <<parameters.docker_tags>> | sed "s/,/\n/g" | sed "s/[^a-zA-Z0-9\n]/-/g" | sed -e "s|^|-t ${IMAGE_BASE}:|")
docker build \
docker build --progress plain \
$(echo -ne $DOCKER_TAGS | tr '\n' ' ') \
-f <<parameters.docker_file>> \
<<parameters.docker_context>>
......@@ -265,7 +266,7 @@ jobs:
DOCKER_TAGS=$(echo -ne <<parameters.docker_tags>> | sed "s/,/\n/g" | sed "s/[^a-zA-Z0-9\n]/-/g" | sed -e "s|^|-t ${IMAGE_BASE}:|")
docker context create buildx-build
docker buildx create --use buildx-build
docker buildx build --platform=<<parameters.platforms>> --target "<<parameters.docker_target>>" --push \
docker buildx build --progress plain --platform=<<parameters.platforms>> --target "<<parameters.docker_target>>" --push \
$(echo -ne $DOCKER_TAGS | tr '\n' ' ') \
-f <<parameters.docker_file>> \
<<parameters.docker_context>>
......@@ -320,7 +321,7 @@ jobs:
DOCKER_TAGS=$(echo -ne <<parameters.docker_tags>> | sed "s/,/\n/g" | sed "s/[^a-zA-Z0-9\n]/-/g" | sed -e "s|^|-t ${IMAGE_BASE}:|")
docker context create buildx-build
docker buildx create --use buildx-build
docker buildx build --platform=<<parameters.platforms>> --target "<<parameters.docker_target>>" --push \
docker buildx build --progress plain --platform=<<parameters.platforms>> --target "<<parameters.docker_target>>" --push \
$(echo -ne $DOCKER_TAGS | tr '\n' ' ') \
-f <<parameters.docker_file>> \
<<parameters.docker_context>>
......@@ -709,6 +710,24 @@ jobs:
name: Upload coverage
command: codecov --verbose --clean --flags <<parameters.coverage_flag>>
contracts-ts-tests:
docker:
- image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
resource_class: large
steps:
- checkout
- attach_workspace: { at: "." }
- restore_cache:
name: Restore pnpm Package Cache
keys:
- pnpm-packages-v2-{{ checksum "pnpm.lock.yaml" }}
- check-changed:
patterns: sdk,contracts-bedrock,contracts
- run:
name: Check generated and build
command: pnpm generate:check
working_directory: packages/contracts-ts
sdk-next-tests:
docker:
- image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
......@@ -1336,6 +1355,13 @@ workflows:
dependencies: "(common-ts|core-utils|sdk)"
requires:
- pnpm-monorepo
- js-lint-test:
name: contracts-ts-tests
coverage_flag: contracts-ts-tests
package_name: contracts-ts
dependencies: '(contracts-bedrock|contracts-ts)'
requires:
- pnpm-monorepo
- js-lint-test:
name: sdk-next-tests
coverage_flag: sdk-next-tests
......@@ -1374,7 +1400,6 @@ workflows:
name: indexer-tests
binary_name: indexer
working_directory: indexer
dependencies: op-bindings
- go-lint-test-build:
name: op-heartbeat tests
binary_name: op-heartbeat
......@@ -1720,6 +1745,21 @@ workflows:
- oplabs-gcr-release
requires:
- hold
- docker-release:
name: op-ufm-docker-release
filters:
tags:
only: /^op-ufm\/v.*/
branches:
ignore: /.*/
docker_file: op-ufm/Dockerfile
docker_name: op-ufm
docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
docker_context: .
context:
- oplabs-gcr-release
requires:
- hold
- docker-release:
name: proxyd-docker-release
filters:
......
......@@ -18,13 +18,14 @@ on:
required: true
type: choice
options:
- ci-builder
- fault-detector
- indexer
- op-node
- op-batcher
- op-proposer
- op-ufm
- proxyd
- indexer
- fault-detector
- ci-builder
prerelease:
description: Increment major/minor/patch as prerelease?
required: false
......
---
title: Using the SDK with OP Stack
title: Using the OP Stack Client SDK
lang: en-US
---
When building applications for use with your OP Stack, you can continue to use [the Optimism JavaScript SDK](https://sdk.optimism.io/).
The main difference is you need to provide some contract addresses to the `CrossDomainMessenger` because they aren't preconfigured.
## Natively supported chains
## Contract addresses
[The OP Stack Client SDK](https://sdk.optimism.io/) natively supports multiple OP Chains: OP, Base, etc.
To see whether a specific OP Chain is supported directly, [see the documentation](https://sdk.optimism.io/enums/l2chainid).
### L1 contract addresses
## Not natively supported chains
The contract addresses are in `.../optimism/packages/contracts-bedrock/deployments/getting-started`, which you created when you deployed the L1 contracts.
If you are using a chain that is *not* natively supported, for example an OP Stack chain [you just created](./getting-started.md), you can continue to use [the OP Stack Client SDK](https://sdk.optimism.io/).
You just need to provide some contract addresses to the `CrossDomainMessenger` because they aren't preconfigured.
### Getting contract addresses
#### L1 contract addresses
If you followed the directions in [Getting Started](./getting-started.md), the contract addresses are in `.../optimism/packages/contracts-bedrock/deployments/getting-started`, which you created when you deployed the L1 contracts.
| Contract name when creating `CrossDomainMessenger` | File with address |
| - | - |
......@@ -22,9 +29,9 @@ The contract addresses are in `.../optimism/packages/contracts-bedrock/deploymen
| `L2OutputOracle` | `L2OutputOracleProxy.json`
### Unneeded contract addresses
#### Unneeded contract addresses
Some contracts are required by the SDK, but not actually used.
Some contracts are required by the SDK as a sanity check, but are not actually used.
For these contracts you can just specify the zero address:
- `StateCommitmentChain`
......@@ -33,7 +40,7 @@ For these contracts you can just specify the zero address:
In JavaScript you can create the zero address using the expression `"0x".padEnd(42, "0")`.
## The CrossChainMessenger object
### The CrossChainMessenger object
These directions assume you are inside the [Hardhat console](https://hardhat.org/hardhat-runner/docs/guides/hardhat-console).
They further assume that your project already includes the Optimism SDK [`@eth-optimism/sdk`](https://www.npmjs.com/package/@eth-optimism/sdk).
......@@ -113,7 +120,7 @@ They further assume that your project already includes the Optimism SDK [`@eth-o
})
```
## Verify SDK functionality
### Verify SDK functionality
To verify the SDK's functionality, transfer some ETH from L1 to L2.
......
......@@ -3,21 +3,27 @@ module github.com/ethereum-optimism/optimism
go 1.19
require (
github.com/BurntSushi/toml v1.3.2
github.com/btcsuite/btcd v0.23.3
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3
github.com/ethereum/go-ethereum v1.11.6
github.com/fsnotify/fsnotify v1.6.0
github.com/go-chi/chi/v5 v5.0.0
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb
github.com/google/go-cmp v0.5.9
github.com/google/gofuzz v1.2.1-0.20220503160820-4a35382e8fc8
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
github.com/hashicorp/golang-lru/v2 v2.0.1
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c
github.com/ipfs/go-datastore v0.6.0
github.com/ipfs/go-ds-leveldb v0.5.0
github.com/jackc/pgtype v1.14.0
github.com/lib/pq v1.10.9
github.com/libp2p/go-libp2p v0.25.1
github.com/libp2p/go-libp2p-pubsub v0.9.3
github.com/libp2p/go-libp2p-testing v0.12.0
......@@ -29,13 +35,17 @@ require (
github.com/pkg/errors v0.9.1
github.com/pkg/profile v1.7.0
github.com/prometheus/client_golang v1.14.0
github.com/rs/cors v1.8.2
github.com/stretchr/testify v1.8.1
github.com/urfave/cli v1.22.2
github.com/urfave/cli/v2 v2.25.7
golang.org/x/crypto v0.6.0
golang.org/x/crypto v0.8.0
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb
golang.org/x/sync v0.1.0
golang.org/x/term v0.6.0
golang.org/x/term v0.7.0
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af
gorm.io/driver/postgres v1.5.2
gorm.io/gorm v1.25.2
)
require (
......@@ -81,7 +91,6 @@ require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/graph-gophers/graphql-go v1.3.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
......@@ -93,9 +102,15 @@ require (
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/ipfs/go-cid v0.3.2 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.3.1 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.15.15 // indirect
github.com/klauspost/cpuid/v2 v2.2.3 // indirect
github.com/koron/go-ssdp v0.0.3 // indirect
......@@ -147,7 +162,6 @@ require (
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/rs/cors v1.8.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
......@@ -165,9 +179,9 @@ require (
go.uber.org/multierr v1.9.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/tools v0.7.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
......
......@@ -11,11 +11,13 @@ github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOv
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8=
github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY=
github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8=
......@@ -69,6 +71,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA=
github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8=
......@@ -88,6 +91,8 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
......@@ -96,6 +101,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
......@@ -177,9 +183,12 @@ github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwv
github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-chi/chi/v5 v5.0.0 h1:DBPx88FjZJH3FsICfDAfIfnb7XxKIYVGG6lOPlhENAg=
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
......@@ -194,6 +203,7 @@ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/j
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
......@@ -211,6 +221,7 @@ github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
......@@ -281,6 +292,7 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
......@@ -341,6 +353,53 @@ github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/
github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk=
github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530 h1:dUJ578zuPEsXjtzOfEF0q9zDAfljJ9oFnTHcQaNkccw=
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c=
github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.1.1 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI=
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw=
github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c h1:Dznn52SgVIVst9UyOT9brctYUgxs+CvVfPaC3jKrA50=
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU=
github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
......@@ -351,6 +410,10 @@ github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZl
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
......@@ -378,6 +441,8 @@ github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk=
github.com/koron/go-ssdp v0.0.3 h1:JivLMY45N76b4p/vsWGOKewBQu6uf39y8l+AQ7sDKx8=
github.com/koron/go-ssdp v0.0.3/go.mod h1:b2MxI6yh02pKrsyNoQUsk4+YNikaGhe4894J+Q5lDvA=
......@@ -389,6 +454,7 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
......@@ -398,6 +464,12 @@ github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awS
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c=
......@@ -434,12 +506,15 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
......@@ -602,15 +677,21 @@ github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZV
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
......@@ -634,6 +715,8 @@ github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
......@@ -650,6 +733,8 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
......@@ -680,6 +765,7 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
......@@ -706,7 +792,11 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
......@@ -717,11 +807,16 @@ go.uber.org/fx v1.19.1 h1:JwYIYAQzXBuBBwSZ1/tn/95pnQO/Sp3yE8lWj9eSAzI=
go.uber.org/fx v1.19.1/go.mod h1:bGK+AEy7XUwTBkqCsK/vDyFF0JJOA6X5KWpNC0e6qTA=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
......@@ -732,19 +827,24 @@ golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w=
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
......@@ -778,6 +878,7 @@ golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
......@@ -793,8 +894,8 @@ golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
......@@ -812,6 +913,7 @@ golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
......@@ -819,8 +921,10 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
......@@ -860,22 +964,23 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
......@@ -893,12 +998,15 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
......@@ -909,6 +1017,8 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
......@@ -961,6 +1071,7 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
......@@ -982,6 +1093,10 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0=
gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8=
gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
......
FROM golang:1.19.0-alpine3.15 as builder
FROM --platform=$BUILDPLATFORM golang:1.19.9-alpine3.16 as builder
RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash
COPY ./indexer /go/indexer
COPY ./.git /go/.git
COPY ./indexer/go.mod /go/indexer/go.mod
COPY ./indexer/go.sum /go/indexer/go.sum
# build indexer with the shared go.mod & go.sum files
COPY ./indexer /app/indexer
COPY ./op-bindings /app/op-bindings
COPY ./op-service /app/op-service
COPY ./op-node /app/op-node
COPY ./go.mod /app/go.mod
COPY ./go.sum /app/go.sum
COPY ./.git /app/.git
WORKDIR /go/indexer
RUN make
WORKDIR /app/indexer
FROM alpine:3.15
RUN go mod download
COPY --from=builder /go/indexer/indexer /usr/local/bin
RUN make indexer
FROM alpine:3.16
COPY --from=builder /app/indexer/indexer /usr/local/bin
CMD ["indexer"]
GITCOMMIT := $(shell git rev-parse HEAD)
GITDATE := $(shell git show -s --format='%ct')
GITVERSION := $(shell cat package.json | jq .version)
LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT)
LDFLAGSSTRING +=-X main.GitDate=$(GITDATE)
LDFLAGSSTRING +=-X main.GitVersion=$(GITVERSION)
LDFLAGS := -ldflags "$(LDFLAGSSTRING)"
indexer:
......
module github.com/ethereum-optimism/optimism/indexer
go 1.19
replace github.com/ethereum/go-ethereum v1.11.6 => github.com/ethereum-optimism/op-geth v1.101106.0-rc.2
require (
github.com/BurntSushi/toml v1.3.0
github.com/ethereum-optimism/optimism v1.0.9
github.com/ethereum/go-ethereum v1.11.6
github.com/go-chi/chi/v5 v5.0.8
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/jackc/pgtype v1.14.0
github.com/lib/pq v1.10.4
github.com/prometheus/client_golang v1.14.0
github.com/rs/cors v1.8.2
github.com/stretchr/testify v1.8.1
github.com/urfave/cli v1.22.9
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa
gorm.io/driver/postgres v1.5.2
gorm.io/gorm v1.25.1
)
require (
github.com/DataDog/zstd v1.5.2 // indirect
github.com/VictoriaMetrics/fastcache v1.10.0 // indirect
github.com/benbjohnson/clock v1.3.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcd v0.23.3 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/btcsuite/btcd/btcutil v1.1.0 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cockroachdb/errors v1.9.1 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 // indirect
github.com/cockroachdb/redact v1.1.3 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/deckarep/golang-set/v2 v2.1.0 // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
github.com/deepmap/oapi-codegen v1.8.2 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/edsrzf/mmap-go v1.1.0 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 // indirect
github.com/fjl/memsize v0.0.1 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
github.com/getsentry/sentry-go v0.18.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/graph-gophers/graphql-go v1.3.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-bexpr v0.1.11 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
github.com/hashicorp/golang-lru/v2 v2.0.1 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect
github.com/huin/goupnp v1.1.0 // indirect
github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c // indirect
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/ipfs/go-cid v0.3.2 // indirect
github.com/ipfs/go-datastore v0.6.0 // indirect
github.com/ipfs/go-log v1.0.5 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.3.1 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.15.15 // indirect
github.com/klauspost/cpuid/v2 v2.2.3 // indirect
github.com/koron/go-ssdp v0.0.3 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.1.0 // indirect
github.com/libp2p/go-libp2p v0.25.1 // indirect
github.com/libp2p/go-libp2p-asn-util v0.2.0 // indirect
github.com/libp2p/go-libp2p-pubsub v0.9.0 // indirect
github.com/libp2p/go-libp2p-testing v0.12.0 // indirect
github.com/libp2p/go-mplex v0.7.0 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-nat v0.1.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect
github.com/libp2p/go-reuseport v0.2.0 // indirect
github.com/libp2p/go-yamux/v4 v4.0.0 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/miekg/dns v1.1.50 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/pointerstructure v1.2.1 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
github.com/multiformats/go-multiaddr v0.8.0 // indirect
github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
github.com/multiformats/go-multibase v0.1.1 // indirect
github.com/multiformats/go-multicodec v0.8.1 // indirect
github.com/multiformats/go-multihash v0.2.1 // indirect
github.com/multiformats/go-multistream v0.4.1 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/onsi/ginkgo/v2 v2.8.1 // indirect
github.com/opencontainers/runtime-spec v1.0.2 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.39.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect
github.com/quic-go/qtls-go1-19 v0.2.0 // indirect
github.com/quic-go/qtls-go1-20 v0.1.0 // indirect
github.com/quic-go/quic-go v0.32.0 // indirect
github.com/quic-go/webtransport-go v0.5.1 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/status-im/keycard-go v0.2.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.5.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/dig v1.16.1 // indirect
go.uber.org/fx v1.19.1 // indirect
go.uber.org/multierr v1.9.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.8.0 // indirect
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/term v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
golang.org/x/tools v0.7.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.1.7 // indirect
nhooyr.io/websocket v1.8.7 // indirect
)
This source diff could not be displayed because it is too large. You can view the blob instead.
package integration_tests
import (
"context"
"database/sql"
"encoding/json"
"fmt"
......@@ -14,10 +13,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethclient/gethclient"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/indexer/db"
......@@ -29,6 +25,7 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-node/withdrawals"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
_ "github.com/lib/pq"
)
......@@ -47,14 +44,12 @@ func TestBedrockIndexer(t *testing.T) {
fromAddr := cfg.Secrets.Addresses().Alice
// wait a couple of blocks
require.NoError(t, e2eutils.WaitBlock(e2eutils.TimeoutCtx(t, 30*time.Second), l2Client, 10))
require.NoError(t, utils.WaitBlock(e2eutils.TimeoutCtx(t, 30*time.Second), l2Client, 10))
l1SB, err := bindings.NewL1StandardBridge(predeploys.DevL1StandardBridgeAddr, l1Client)
require.NoError(t, err)
l2SB, err := bindings.NewL2StandardBridge(predeploys.L2StandardBridgeAddr, l2Client)
require.NoError(t, err)
portal, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client)
require.NoError(t, err)
l1Opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Alice, cfg.L1ChainIDBig())
require.NoError(t, err)
l2Opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Alice, cfg.L2ChainIDBig())
......@@ -104,7 +99,7 @@ func TestBedrockIndexer(t *testing.T) {
l1Opts.Value = big.NewInt(params.Ether)
depTx, err := l1SB.DepositETH(l1Opts, 200_000, nil)
require.NoError(t, err)
depReceipt, err := e2eutils.WaitReceiptOK(e2eutils.TimeoutCtx(t, 10*time.Second), l1Client, depTx.Hash())
depReceipt, err := utils.WaitReceiptOK(e2eutils.TimeoutCtx(t, 10*time.Second), l1Client, depTx.Hash())
require.NoError(t, err)
require.Greaterf(t, len(depReceipt.Logs), 0, "must have logs")
var l2Hash common.Hash
......@@ -119,12 +114,12 @@ func TestBedrockIndexer(t *testing.T) {
l2Hash = tx.Hash()
}
require.NotEqual(t, common.Hash{}, l2Hash)
_, err = e2eutils.WaitReceiptOK(e2eutils.TimeoutCtx(t, 15*time.Second), l2Client, l2Hash)
_, err = utils.WaitReceiptOK(e2eutils.TimeoutCtx(t, 15*time.Second), l2Client, l2Hash)
require.NoError(t, err)
// Poll for indexer deposit
var depPage *db.PaginatedDeposits
require.NoError(t, e2eutils.WaitFor(e2eutils.TimeoutCtx(t, 30*time.Second), 100*time.Millisecond, func() (bool, error) {
require.NoError(t, utils.WaitFor(e2eutils.TimeoutCtx(t, 30*time.Second), 100*time.Millisecond, func() (bool, error) {
res := new(db.PaginatedDeposits)
err := getJSON(makeURL(fmt.Sprintf("v1/deposits/%s", fromAddr)), res)
if err != nil {
......@@ -155,11 +150,11 @@ func TestBedrockIndexer(t *testing.T) {
l2Opts.Value = big.NewInt(0.5 * params.Ether)
wdTx, err := l2SB.Withdraw(l2Opts, predeploys.LegacyERC20ETHAddr, big.NewInt(0.5*params.Ether), 0, nil)
require.NoError(t, err)
wdReceipt, err := e2eutils.WaitReceiptOK(e2eutils.TimeoutCtx(t, 30*time.Second), l2Client, wdTx.Hash())
wdReceipt, err := utils.WaitReceiptOK(e2eutils.TimeoutCtx(t, 30*time.Second), l2Client, wdTx.Hash())
require.NoError(t, err)
var wdPage *db.PaginatedWithdrawals
require.NoError(t, e2eutils.WaitFor(e2eutils.TimeoutCtx(t, 30*time.Second), 100*time.Millisecond, func() (bool, error) {
require.NoError(t, utils.WaitFor(e2eutils.TimeoutCtx(t, 30*time.Second), 100*time.Millisecond, func() (bool, error) {
res := new(db.PaginatedWithdrawals)
err := getJSON(makeURL(fmt.Sprintf("v1/withdrawals/%s", fromAddr)), res)
if err != nil {
......@@ -189,50 +184,11 @@ func TestBedrockIndexer(t *testing.T) {
require.Equal(t, db.ETHL2Token, withdrawal.L2Token)
require.NotEmpty(t, withdrawal.GUID)
finBlockNum, err := withdrawals.WaitForFinalizationPeriod(
e2eutils.TimeoutCtx(t, time.Minute),
l1Client,
predeploys.DevOptimismPortalAddr,
wdReceipt.BlockNumber,
)
require.NoError(t, err)
finHeader, err := l2Client.HeaderByNumber(context.Background(), big.NewInt(int64(finBlockNum)))
require.NoError(t, err)
rpcClient, err := rpc.Dial(sys.Nodes["sequencer"].HTTPEndpoint())
require.NoError(t, err)
proofCl := gethclient.New(rpcClient)
receiptCl := ethclient.NewClient(rpcClient)
oracle, err := bindings.NewL2OutputOracleCaller(predeploys.DevL2OutputOracleAddr, l1Client)
require.Nil(t, err)
wParams, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, wdTx.Hash(), finHeader, oracle)
require.NoError(t, err)
l1Opts.Value = big.NewInt(0)
withdrawalTx := bindings.TypesWithdrawalTransaction{
Nonce: wParams.Nonce,
Sender: wParams.Sender,
Target: wParams.Target,
Value: wParams.Value,
GasLimit: wParams.GasLimit,
Data: wParams.Data,
}
// Prove our withdrawal
proveTx, err := portal.ProveWithdrawalTransaction(
l1Opts,
withdrawalTx,
wParams.L2OutputIndex,
wParams.OutputRootProof,
wParams.WithdrawalProof,
)
require.NoError(t, err)
proveReceipt, err := e2eutils.WaitReceiptOK(e2eutils.TimeoutCtx(t, time.Minute), l1Client, proveTx.Hash())
require.NoError(t, err)
wdParams, proveReceipt := op_e2e.ProveWithdrawal(t, cfg, l1Client, sys.Nodes["sequencer"], cfg.Secrets.Alice, wdReceipt)
wdPage = nil
require.NoError(t, e2eutils.WaitFor(e2eutils.TimeoutCtx(t, 30*time.Second), 100*time.Millisecond, func() (bool, error) {
require.NoError(t, utils.WaitFor(e2eutils.TimeoutCtx(t, 30*time.Second), 100*time.Millisecond, func() (bool, error) {
res := new(db.PaginatedWithdrawals)
err := getJSON(makeURL(fmt.Sprintf("v1/withdrawals/%s", fromAddr)), res)
if err != nil {
......@@ -251,27 +207,13 @@ func TestBedrockIndexer(t *testing.T) {
require.Equal(t, proveReceipt.TxHash.String(), *wd.BedrockProvenTxHash)
require.Nil(t, wd.BedrockFinalizedTxHash)
// Wait for the finalization period to elapse
_, err = withdrawals.WaitForFinalizationPeriod(
e2eutils.TimeoutCtx(t, time.Minute),
l1Client,
predeploys.DevOptimismPortalAddr,
finHeader.Number,
)
require.NoError(t, err)
// Send our finalize withdrawal transaction
finTx, err := portal.FinalizeWithdrawalTransaction(
l1Opts,
withdrawalTx,
)
require.NoError(t, err)
finReceipt, err := e2eutils.WaitReceiptOK(e2eutils.TimeoutCtx(t, time.Minute), l1Client, finTx.Hash())
require.NoError(t, err)
// Finalize withdrawal
err = withdrawals.WaitForFinalizationPeriod(e2eutils.TimeoutCtx(t, 30*time.Second), l1Client, predeploys.DevOptimismPortalAddr, proveReceipt.BlockNumber)
require.Nil(t, err)
finReceipt := op_e2e.FinalizeWithdrawal(t, cfg, l1Client, cfg.Secrets.Alice, wdReceipt, wdParams)
wdPage = nil
require.NoError(t, e2eutils.WaitFor(e2eutils.TimeoutCtx(t, 30*time.Second), 100*time.Millisecond, func() (bool, error) {
require.NoError(t, utils.WaitFor(e2eutils.TimeoutCtx(t, 30*time.Second), 100*time.Millisecond, func() (bool, error) {
res := new(db.PaginatedWithdrawals)
err := getJSON(makeURL(fmt.Sprintf("v1/withdrawals/%s", fromAddr)), res)
if err != nil {
......
......@@ -56,6 +56,9 @@
"inputs": ["default", "testing", "^production"],
"dependsOn": ["^build"]
},
"generate": {
"dependsOn": ["^build"]
},
"build:contracts": {
"inputs": [
"configsProject",
......
......@@ -28,3 +28,7 @@ $ make devtools
```
The geth docs for `abigen` can be found [here](https://geth.ethereum.org/docs/dapp/native-bindings).
## See also
TypeScript bindings are also generated in [@eth-optimism/contracts-ts](../packages/contracts-ts/)
......@@ -2,6 +2,9 @@ package predeploys
import "github.com/ethereum/go-ethereum/common"
// TODO - we should get a single toml yaml or json file source of truth in @eth-optimism/bedrock package
// This needs to be kept in sync with @eth-optimism/contracts-ts/wagmi.config.ts which also specifies this
// To improve robustness and maintainability contracts-bedrock should export all addresses
const (
L2ToL1MessagePasser = "0x4200000000000000000000000000000000000016"
DeployerWhitelist = "0x4200000000000000000000000000000000000002"
......
package predeploys
import "github.com/ethereum/go-ethereum/common"
const (
LegacyERC20ETH = "0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000"
)
var (
LegacyERC20ETHAddr = common.HexToAddress(LegacyERC20ETH)
)
......@@ -20,35 +20,3 @@ to see a list of available options.
`op-challenger` is configurable via command line flags and environment variables. The help menu
shows the available config options and can be accessed by running `./op-challenger --help`.
Note that there are many global options, but the most important ones are:
- `OP_CHALLENGER_L1_ETH_RPC`: An L1 Ethereum RPC URL
- `OP_CHALLENGER_ROLLUP_RPC`: A Rollup Node RPC URL
- `OP_CHALLENGER_L2OO_ADDRESS`: The L2OutputOracle Contract Address
- `OP_CHALLENGER_DGF_ADDRESS`: Dispute Game Factory Contract Address
Here is a reduced output from running `./op-challenger --help`:
```bash
NAME:
op-challenger - Modular Challenger Agent
USAGE:
main [global options] command [command options] [arguments...]
VERSION:
1.0.0
DESCRIPTION:
A modular op-stack challenge agent for output dispute games written in golang.
COMMANDS:
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--l1-eth-rpc value HTTP provider URL for L1. [$OP_CHALLENGER_L1_ETH_RPC]
--rollup-rpc value HTTP provider URL for the rollup node. [$OP_CHALLENGER_ROLLUP_RPC]
--l2oo-address value Address of the L2OutputOracle contract. [$OP_CHALLENGER_L2OO_ADDRESS]
--dgf-address value Address of the DisputeGameFactory contract. [$OP_CHALLENGER_DGF_ADDRESS]
...
--help, -h show help
--version, -v print the version
```
......@@ -35,16 +35,21 @@ func Main(logger log.Logger, cfg *config.Config) error {
if err != nil {
return fmt.Errorf("failed to create the responder: %w", err)
}
gameDepth := 4
trace := fault.NewAlphabetProvider(cfg.AlphabetTrace, uint64(gameDepth))
trace := fault.NewAlphabetProvider(cfg.AlphabetTrace, uint64(cfg.GameDepth))
agent := fault.NewAgent(loader, gameDepth, trace, responder, cfg.AgreeWithProposedOutput, logger)
agent := fault.NewAgent(loader, cfg.GameDepth, trace, responder, cfg.AgreeWithProposedOutput, logger)
caller, err := fault.NewFaultCallerFromBindings(cfg.GameAddress, client, logger)
if err != nil {
return fmt.Errorf("failed to bind the fault contract: %w", err)
}
logger.Info("Fault game started")
for {
logger.Info("Performing action")
_ = agent.Act()
caller.LogGameInfo()
time.Sleep(300 * time.Millisecond)
}
}
......@@ -14,4 +14,11 @@ MALLORY_KEY="28d7045146193f5f4eeb151c4843544b1b0d30a7ac1680c845a416fac65a7715"
FAULT_GAME_ADDRESS="0x8daf17a20c9dba35f005b6324f493785d239719d"
./bin/op-challenger --l1-eth-rpc http://localhost:8545 --alphabet "abcdefgh" --game-address $FAULT_GAME_ADDRESS --private-key $CHARLIE_KEY --num-confirmations 1 --agree-with-proposed-output=true
./bin/op-challenger \
--l1-eth-rpc http://localhost:8545 \
--alphabet "abcdefgh" \
--game-address $FAULT_GAME_ADDRESS \
--private-key $CHARLIE_KEY \
--num-confirmations 1 \
--game-depth 4 \
--agree-with-proposed-output=true
......@@ -16,6 +16,7 @@ var (
gameAddressValue = "0xaa00000000000000000000000000000000000000"
alphabetTrace = "abcdefghijz"
agreeWithProposedOutput = "true"
gameDepth = "4"
)
func TestLogLevel(t *testing.T) {
......@@ -35,12 +36,12 @@ func TestLogLevel(t *testing.T) {
func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs())
defaultCfg := config.NewConfig(l1EthRpc, common.HexToAddress(gameAddressValue), alphabetTrace, true)
defaultCfg := config.NewConfig(l1EthRpc, common.HexToAddress(gameAddressValue), alphabetTrace, true, 4)
require.Equal(t, defaultCfg, cfg)
}
func TestDefaultConfigIsValid(t *testing.T) {
cfg := config.NewConfig(l1EthRpc, common.HexToAddress(gameAddressValue), alphabetTrace, true)
cfg := config.NewConfig(l1EthRpc, common.HexToAddress(gameAddressValue), alphabetTrace, true, 4)
require.NoError(t, cfg.Check())
}
......@@ -109,6 +110,18 @@ func TestAgreeWithProposedOutput(t *testing.T) {
})
}
func TestGameDepth(t *testing.T) {
t.Run("Required", func(t *testing.T) {
verifyArgsInvalid(t, "flag game-depth is required", addRequiredArgsExcept("--game-depth"))
})
t.Run("Valid", func(t *testing.T) {
value := "4"
cfg := configForArgs(t, addRequiredArgsExcept("--game-depth", "--game-depth="+value))
require.Equal(t, value, fmt.Sprint(cfg.GameDepth))
})
}
func verifyArgsInvalid(t *testing.T, messageContains string, cliArgs []string) {
_, _, err := runWithArgs(cliArgs)
require.ErrorContains(t, err, messageContains)
......@@ -146,6 +159,7 @@ func addRequiredArgsExcept(name string, optionalArgs ...string) []string {
func requiredArgs() map[string]string {
return map[string]string{
"--game-depth": gameDepth,
"--agree-with-proposed-output": agreeWithProposedOutput,
"--l1-eth-rpc": l1EthRpc,
"--game-address": gameAddressValue,
......
......@@ -25,6 +25,7 @@ type Config struct {
GameAddress common.Address // Address of the fault game
AlphabetTrace string // String for the AlphabetTraceProvider
AgreeWithProposedOutput bool // Temporary config if we agree or disagree with the posted output
GameDepth int // Depth of the game tree
TxMgrConfig txmgr.CLIConfig
}
......@@ -34,6 +35,7 @@ func NewConfig(
GameAddress common.Address,
AlphabetTrace string,
AgreeWithProposedOutput bool,
GameDepth int,
) Config {
return Config{
L1EthRpc: l1EthRpc,
......@@ -41,6 +43,7 @@ func NewConfig(
AlphabetTrace: AlphabetTrace,
TxMgrConfig: txmgr.NewCLIConfig(l1EthRpc),
AgreeWithProposedOutput: AgreeWithProposedOutput,
GameDepth: GameDepth,
}
}
......@@ -78,6 +81,7 @@ func NewConfigFromCLI(ctx *cli.Context) (*Config, error) {
GameAddress: dgfAddress,
AlphabetTrace: ctx.String(flags.AlphabetFlag.Name),
AgreeWithProposedOutput: ctx.Bool(flags.AgreeWithProposedOutputFlag.Name),
GameDepth: ctx.Int(flags.GameDepthFlag.Name),
TxMgrConfig: txMgrConfig,
}, nil
}
......@@ -13,10 +13,11 @@ var (
validGameAddress = common.HexToAddress("0x7bdd3b028C4796eF0EAf07d11394d0d9d8c24139")
validAlphabetTrace = "abcdefgh"
agreeWithProposedOutput = true
gameDepth = 4
)
func validConfig() Config {
cfg := NewConfig(validL1EthRpc, validGameAddress, validAlphabetTrace, agreeWithProposedOutput)
cfg := NewConfig(validL1EthRpc, validGameAddress, validAlphabetTrace, agreeWithProposedOutput, gameDepth)
return cfg
}
......
......@@ -95,7 +95,8 @@ func (a *Agent) step(claim Claim, game Game) error {
return nil
}
if game.AgreeWithClaimLevel(claim) {
agreeWithClaimLevel := game.AgreeWithClaimLevel(claim)
if agreeWithClaimLevel {
a.log.Warn("Agree with leaf claim, skipping step", "claim_depth", claim.Depth(), "maxDepth", a.maxDepth)
return nil
}
......@@ -106,7 +107,7 @@ func (a *Agent) step(claim Claim, game Game) error {
}
a.log.Info("Attempting step", "claim_depth", claim.Depth(), "maxDepth", a.maxDepth)
step, err := a.solver.AttemptStep(claim)
step, err := a.solver.AttemptStep(claim, agreeWithClaimLevel)
if err != nil {
a.log.Warn("Failed to get a step", "err", err)
return err
......
......@@ -49,7 +49,7 @@ func (ap *AlphabetProvider) Get(i uint64) (common.Hash, error) {
func (ap *AlphabetProvider) AbsolutePreState() []byte {
out := make([]byte, 32)
out[31] = 140 // ascii character 140 is "`"
out[31] = 96 // ascii character 96 is "`"
return out
}
......
package fault
import (
"context"
"math/big"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
)
type FaultDisputeGameCaller interface {
Status(opts *bind.CallOpts) (uint8, error)
ClaimDataLen(opts *bind.CallOpts) (*big.Int, error)
}
type FaultCaller struct {
FaultDisputeGameCaller
log log.Logger
fdgAddr common.Address
}
func NewFaultCaller(fdgAddr common.Address, caller FaultDisputeGameCaller, log log.Logger) *FaultCaller {
return &FaultCaller{
caller,
log,
fdgAddr,
}
}
func NewFaultCallerFromBindings(fdgAddr common.Address, client *ethclient.Client, log log.Logger) (*FaultCaller, error) {
caller, err := bindings.NewFaultDisputeGameCaller(fdgAddr, client)
if err != nil {
return nil, err
}
return &FaultCaller{
caller,
log,
fdgAddr,
}, nil
}
// LogGameInfo logs the game info.
func (fc *FaultCaller) LogGameInfo() {
status, err := fc.GetGameStatus(context.Background())
if err != nil {
fc.log.Error("failed to get game status", "err", err)
return
}
claimLen, err := fc.GetClaimDataLength(context.Background())
if err != nil {
fc.log.Error("failed to get claim count", "err", err)
return
}
fc.log.Info("Game info", "addr", fc.fdgAddr, "claims", claimLen, "status", GameStatusString(status))
}
// GetGameStatus returns the current game status.
// 0: In Progress
// 1: Challenger Won
// 2: Defender Won
func (fc *FaultCaller) GetGameStatus(ctx context.Context) (uint8, error) {
return fc.Status(&bind.CallOpts{Context: ctx})
}
func (fc *FaultCaller) LogGameStatus() {
status, err := fc.GetGameStatus(context.Background())
if err != nil {
fc.log.Error("failed to get game status", "err", err)
return
}
fc.log.Info("Game status", "status", GameStatusString(status))
}
// GetClaimDataLength returns the number of claims in the game.
func (fc *FaultCaller) GetClaimDataLength(ctx context.Context) (*big.Int, error) {
return fc.ClaimDataLen(&bind.CallOpts{Context: ctx})
}
func (fc *FaultCaller) LogClaimDataLength() {
claimLen, err := fc.GetClaimDataLength(context.Background())
if err != nil {
fc.log.Error("failed to get claim count", "err", err)
return
}
fc.log.Info("Number of claims", "length", claimLen)
}
// GameStatusString returns the current game status as a string.
func GameStatusString(status uint8) string {
switch status {
case 0:
return "In Progress"
case 1:
return "Challenger Won"
case 2:
return "Defender Won"
default:
return "Unknown"
}
}
package fault
import (
"context"
"errors"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
var (
testAddr = common.HexToAddress("0x1234567890123456789012345678901234567890")
errMock = errors.New("mock error")
)
type mockFaultDisputeGameCaller struct {
status uint8
errStatus bool
claimDataLen *big.Int
errClaimDataLen bool
}
func (m *mockFaultDisputeGameCaller) Status(opts *bind.CallOpts) (uint8, error) {
if m.errStatus {
return 0, errMock
}
return m.status, nil
}
func (m *mockFaultDisputeGameCaller) ClaimDataLen(opts *bind.CallOpts) (*big.Int, error) {
if m.errClaimDataLen {
return nil, errMock
}
return m.claimDataLen, nil
}
func TestFaultCaller_GetGameStatus(t *testing.T) {
tests := []struct {
name string
caller FaultDisputeGameCaller
expectedStatus uint8
expectedErr error
}{
{
name: "success",
caller: &mockFaultDisputeGameCaller{
status: 1,
},
expectedStatus: 1,
expectedErr: nil,
},
{
name: "error",
caller: &mockFaultDisputeGameCaller{
errStatus: true,
},
expectedStatus: 0,
expectedErr: errMock,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
fc := NewFaultCaller(testAddr, test.caller, nil)
status, err := fc.GetGameStatus(context.Background())
require.Equal(t, test.expectedStatus, status)
require.Equal(t, test.expectedErr, err)
})
}
}
func TestFaultCaller_GetClaimDataLength(t *testing.T) {
tests := []struct {
name string
caller FaultDisputeGameCaller
expectedClaimDataLen *big.Int
expectedErr error
}{
{
name: "success",
caller: &mockFaultDisputeGameCaller{
claimDataLen: big.NewInt(1),
},
expectedClaimDataLen: big.NewInt(1),
expectedErr: nil,
},
{
name: "error",
caller: &mockFaultDisputeGameCaller{
errClaimDataLen: true,
},
expectedClaimDataLen: nil,
expectedErr: errMock,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
fc := NewFaultCaller(testAddr, test.caller, nil)
claimDataLen, err := fc.GetClaimDataLength(context.Background())
require.Equal(t, test.expectedClaimDataLen, claimDataLen)
require.Equal(t, test.expectedErr, err)
})
}
}
package cannon
import (
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
"github.com/ethereum-optimism/optimism/op-challenger/fault"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
const proofsDir = "proofs"
type proofData struct {
ClaimValue hexutil.Bytes `json:"post"`
StateData hexutil.Bytes `json:"state-data"`
ProofData hexutil.Bytes `json:"proof-data"`
}
type CannonTraceProvider struct {
dir string
}
func NewCannonTraceProvider(dataDir string) *CannonTraceProvider {
return &CannonTraceProvider{
dir: dataDir,
}
}
func (p *CannonTraceProvider) Get(i uint64) (common.Hash, error) {
proof, err := p.loadProof(i)
if err != nil {
return common.Hash{}, err
}
value := common.BytesToHash(proof.ClaimValue)
if value == (common.Hash{}) {
return common.Hash{}, errors.New("proof missing post hash")
}
return value, nil
}
func (p *CannonTraceProvider) GetPreimage(i uint64) ([]byte, error) {
proof, err := p.loadProof(i)
if err != nil {
return nil, err
}
value := ([]byte)(proof.StateData)
if len(value) == 0 {
return nil, errors.New("proof missing state data")
}
return value, nil
}
func (p *CannonTraceProvider) AbsolutePreState() []byte {
panic("absolute prestate not yet supported")
}
func (p *CannonTraceProvider) loadProof(i uint64) (*proofData, error) {
path := filepath.Join(p.dir, proofsDir, fmt.Sprintf("%d.json", i))
file, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("cannot open proof file (%v): %w", path, err)
}
defer file.Close()
var proof proofData
err = json.NewDecoder(file).Decode(&proof)
if err != nil {
return nil, fmt.Errorf("failed to read proof (%v): %w", path, err)
}
return &proof, nil
}
var _ fault.TraceProvider = (*CannonTraceProvider)(nil)
package cannon
import (
"embed"
_ "embed"
"os"
"path/filepath"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
//go:embed test_data
var testData embed.FS
func TestGet(t *testing.T) {
provider := setupWithTestData(t)
t.Run("ExistingProof", func(t *testing.T) {
value, err := provider.Get(0)
require.NoError(t, err)
require.Equal(t, common.HexToHash("0x45fd9aa59768331c726e719e76aa343e73123af888804604785ae19506e65e87"), value)
})
t.Run("ProofUnavailable", func(t *testing.T) {
_, err := provider.Get(7)
require.ErrorIs(t, err, os.ErrNotExist)
})
t.Run("MissingPostHash", func(t *testing.T) {
_, err := provider.Get(1)
require.ErrorContains(t, err, "missing post hash")
})
t.Run("IgnoreUnknownFields", func(t *testing.T) {
value, err := provider.Get(2)
require.NoError(t, err)
expected := common.HexToHash("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
require.Equal(t, expected, value)
})
}
func TestGetPreimage(t *testing.T) {
provider := setupWithTestData(t)
t.Run("ExistingProof", func(t *testing.T) {
value, err := provider.GetPreimage(0)
require.NoError(t, err)
expected := common.Hex2Bytes("b8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f400000000000000000000000000000000000000000000000000000000000000000000000000")
require.Equal(t, expected, value)
})
t.Run("ProofUnavailable", func(t *testing.T) {
_, err := provider.GetPreimage(7)
require.ErrorIs(t, err, os.ErrNotExist)
})
t.Run("MissingStateData", func(t *testing.T) {
_, err := provider.GetPreimage(1)
require.ErrorContains(t, err, "missing state data")
})
t.Run("IgnoreUnknownFields", func(t *testing.T) {
value, err := provider.GetPreimage(2)
require.NoError(t, err)
expected := common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")
require.Equal(t, expected, value)
})
}
func setupWithTestData(t *testing.T) *CannonTraceProvider {
srcDir := filepath.Join("test_data", "proofs")
entries, err := testData.ReadDir(srcDir)
require.NoError(t, err)
dataDir := t.TempDir()
require.NoError(t, os.Mkdir(filepath.Join(dataDir, proofsDir), 0o777))
for _, entry := range entries {
path := filepath.Join(srcDir, entry.Name())
file, err := testData.ReadFile(path)
require.NoErrorf(t, err, "reading %v", path)
err = os.WriteFile(filepath.Join(dataDir, "proofs", entry.Name()), file, 0o644)
require.NoErrorf(t, err, "writing %v", path)
}
return NewCannonTraceProvider(dataDir)
}
{"step":0,"pre":"0x71f9eb93ff904e5c03c3425228ef75766db0c906ad239df9a7a7f0d9c6a89705","post":"0x45fd9aa59768331c726e719e76aa343e73123af888804604785ae19506e65e87","state-data":"0xb8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f400000000000000000000000000000000000000000000000000000000000000000000000000","proof-data":"0x08028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004240210960000000c0000003403e00008000000008fa100040000102571c0e460346a89963488f904199fc7b4dc3dce2ddadfe484510463ae5014a79df9d922ef2cb84325e4e13ad98828ed29937c1440d8ea9eb19cab7474243c2d0b1a83646e420529153298f3a914a2550658c930f5e519b1d8dd151cf828116697d27264e6fad331820ecf3855adcc68dc529acfc33ecfa45a3a33c9ac766edc1f437988f2abab9dce36d3bac27b0f7b58a06d125acd50a1bf14bb8c7f6c1618465a532f945043b5a9ebc800d7336673019654eb76f8c10cff4f794ee586dc9992c318cef3dfa57032e2dd2fc5cb2dcfebd05551301704dd37a7c169448ec02574f706e38c20963616dae4e03cc91f39a4c3f9608119212965b72948f0ee15feb48b758f050691197816dc3ca919bbb3b50624d195c82d644025647ac8ba07206e5eb830799dfa896506743e81856edf8a31fef737fb4f44501dc71f019bdb12ed9cf0b9fba40ef98e5091b70484ba4f6af7711ec8b0ba4f4f2c4b11455a9e071f465817724159ddeea1170f4dd912c3a5a10ec6b046aa3c4a9febddfeeaa47e3ef06e1758694515562c958dc1b018149c7e4fcd91b9033ee216fea2ea498acd065e61fd436f26c31654bfd27c13ab67707384ad7a84a4b085e890e998e8a9655da954db3d279d598343a4706a2272fca526caeddb017627ecaf0138f1446c82e16d0926c0c510773e2b439c2c71414deb9b739fa370c010380d9ed5927fd7f4bb84ac22747f1bd405830b65d9e04c5efddc2c4dc89ba294c7568b9952193172d75ed8ea3e0fe57c8ad6636da54921ab52a8a0f54920d124f43b9fd3577690140cb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef6834d8ef8faaf96b7b45235297538a266eb882b8b5680f621aab3417d43cdc2eb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","step-input":"0xf8e0cb960000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000e2b8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f4000000000000000000000000000000000000000000000000000000000000000000000000000a3900000a39040000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffd0000000000000000000000000000000000000000000000000000000000000000000000000000000070008028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004240210960000000c0000003403e00008000000008fa100040000102571c0e460346a89963488f904199fc7b4dc3dce2ddadfe484510463ae5014a79df9d922ef2cb84325e4e13ad98828ed29937c1440d8ea9eb19cab7474243c2d0b1a83646e420529153298f3a914a2550658c930f5e519b1d8dd151cf828116697d27264e6fad331820ecf3855adcc68dc529acfc33ecfa45a3a33c9ac766edc1f437988f2abab9dce36d3bac27b0f7b58a06d125acd50a1bf14bb8c7f6c1618465a532f945043b5a9ebc800d7336673019654eb76f8c10cff4f794ee586dc9992c318cef3dfa57032e2dd2fc5cb2dcfebd05551301704dd37a7c169448ec02574f706e38c20963616dae4e03cc91f39a4c3f9608119212965b72948f0ee15feb48b758f050691197816dc3ca919bbb3b50624d195c82d644025647ac8ba07206e5eb830799dfa896506743e81856edf8a31fef737fb4f44501dc71f019bdb12ed9cf0b9fba40ef98e5091b70484ba4f6af7711ec8b0ba4f4f2c4b11455a9e071f465817724159ddeea1170f4dd912c3a5a10ec6b046aa3c4a9febddfeeaa47e3ef06e1758694515562c958dc1b018149c7e4fcd91b9033ee216fea2ea498acd065e61fd436f26c31654bfd27c13ab67707384ad7a84a4b085e890e998e8a9655da954db3d279d598343a4706a2272fca526caeddb017627ecaf0138f1446c82e16d0926c0c510773e2b439c2c71414deb9b739fa370c010380d9ed5927fd7f4bb84ac22747f1bd405830b65d9e04c5efddc2c4dc89ba294c7568b9952193172d75ed8ea3e0fe57c8ad6636da54921ab52a8a0f54920d124f43b9fd3577690140cb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef6834d8ef8faaf96b7b45235297538a266eb882b8b5680f621aab3417d43cdc2eb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","oracle-input":"0x"}
{"foo":0,"bar":"0x71f9eb93ff904e5c03c3425228ef75766db0c906ad239df9a7a7f0d9c6a89705","post":"0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","state-data":"0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc","proof-data":"0x08028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004240210960000000c0000003403e00008000000008fa100040000102571c0e460346a89963488f904199fc7b4dc3dce2ddadfe484510463ae5014a79df9d922ef2cb84325e4e13ad98828ed29937c1440d8ea9eb19cab7474243c2d0b1a83646e420529153298f3a914a2550658c930f5e519b1d8dd151cf828116697d27264e6fad331820ecf3855adcc68dc529acfc33ecfa45a3a33c9ac766edc1f437988f2abab9dce36d3bac27b0f7b58a06d125acd50a1bf14bb8c7f6c1618465a532f945043b5a9ebc800d7336673019654eb76f8c10cff4f794ee586dc9992c318cef3dfa57032e2dd2fc5cb2dcfebd05551301704dd37a7c169448ec02574f706e38c20963616dae4e03cc91f39a4c3f9608119212965b72948f0ee15feb48b758f050691197816dc3ca919bbb3b50624d195c82d644025647ac8ba07206e5eb830799dfa896506743e81856edf8a31fef737fb4f44501dc71f019bdb12ed9cf0b9fba40ef98e5091b70484ba4f6af7711ec8b0ba4f4f2c4b11455a9e071f465817724159ddeea1170f4dd912c3a5a10ec6b046aa3c4a9febddfeeaa47e3ef06e1758694515562c958dc1b018149c7e4fcd91b9033ee216fea2ea498acd065e61fd436f26c31654bfd27c13ab67707384ad7a84a4b085e890e998e8a9655da954db3d279d598343a4706a2272fca526caeddb017627ecaf0138f1446c82e16d0926c0c510773e2b439c2c71414deb9b739fa370c010380d9ed5927fd7f4bb84ac22747f1bd405830b65d9e04c5efddc2c4dc89ba294c7568b9952193172d75ed8ea3e0fe57c8ad6636da54921ab52a8a0f54920d124f43b9fd3577690140cb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef6834d8ef8faaf96b7b45235297538a266eb882b8b5680f621aab3417d43cdc2eb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","step-input":"0xf8e0cb960000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000e2b8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f4000000000000000000000000000000000000000000000000000000000000000000000000000a3900000a39040000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffd0000000000000000000000000000000000000000000000000000000000000000000000000000000070008028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004240210960000000c0000003403e00008000000008fa100040000102571c0e460346a89963488f904199fc7b4dc3dce2ddadfe484510463ae5014a79df9d922ef2cb84325e4e13ad98828ed29937c1440d8ea9eb19cab7474243c2d0b1a83646e420529153298f3a914a2550658c930f5e519b1d8dd151cf828116697d27264e6fad331820ecf3855adcc68dc529acfc33ecfa45a3a33c9ac766edc1f437988f2abab9dce36d3bac27b0f7b58a06d125acd50a1bf14bb8c7f6c1618465a532f945043b5a9ebc800d7336673019654eb76f8c10cff4f794ee586dc9992c318cef3dfa57032e2dd2fc5cb2dcfebd05551301704dd37a7c169448ec02574f706e38c20963616dae4e03cc91f39a4c3f9608119212965b72948f0ee15feb48b758f050691197816dc3ca919bbb3b50624d195c82d644025647ac8ba07206e5eb830799dfa896506743e81856edf8a31fef737fb4f44501dc71f019bdb12ed9cf0b9fba40ef98e5091b70484ba4f6af7711ec8b0ba4f4f2c4b11455a9e071f465817724159ddeea1170f4dd912c3a5a10ec6b046aa3c4a9febddfeeaa47e3ef06e1758694515562c958dc1b018149c7e4fcd91b9033ee216fea2ea498acd065e61fd436f26c31654bfd27c13ab67707384ad7a84a4b085e890e998e8a9655da954db3d279d598343a4706a2272fca526caeddb017627ecaf0138f1446c82e16d0926c0c510773e2b439c2c71414deb9b739fa370c010380d9ed5927fd7f4bb84ac22747f1bd405830b65d9e04c5efddc2c4dc89ba294c7568b9952193172d75ed8ea3e0fe57c8ad6636da54921ab52a8a0f54920d124f43b9fd3577690140cb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef6834d8ef8faaf96b7b45235297538a266eb882b8b5680f621aab3417d43cdc2eb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","oracle-input":"0x"}
......@@ -7,6 +7,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
......@@ -55,6 +56,11 @@ func (r *faultResponder) buildFaultAttackData(parentContractIndex int, pivot [32
)
}
// buildResolveData creates the transaction data for the Resolve function.
func (r *faultResponder) buildResolveData() ([]byte, error) {
return r.fdgAbi.Pack("resolve")
}
// BuildTx builds the transaction for the [faultResponder].
func (r *faultResponder) BuildTx(ctx context.Context, response Claim) ([]byte, error) {
if response.DefendsParent() {
......@@ -72,6 +78,30 @@ func (r *faultResponder) BuildTx(ctx context.Context, response Claim) ([]byte, e
}
}
// CanResolve determines if the resolve function on the fault dispute game contract
// would succeed. Returns true if the game can be resolved, otherwise false.
func (r *faultResponder) CanResolve(ctx context.Context) bool {
txData, err := r.buildResolveData()
if err != nil {
return false
}
_, err = r.txMgr.Call(ctx, ethereum.CallMsg{
To: &r.fdgAddr,
Data: txData,
}, nil)
return err == nil
}
// Resolve executes a resolve transaction to resolve a fault dispute game.
func (r *faultResponder) Resolve(ctx context.Context) error {
txData, err := r.buildResolveData()
if err != nil {
return err
}
return r.sendTxAndWait(ctx, txData)
}
// Respond takes a [Claim] and executes the response action.
func (r *faultResponder) Respond(ctx context.Context, response Claim) error {
txData, err := r.BuildTx(ctx, response)
......
......@@ -10,6 +10,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
......@@ -25,6 +26,7 @@ var (
type mockTxManager struct {
from common.Address
sends int
calls int
sendFails bool
}
......@@ -40,6 +42,14 @@ func (m *mockTxManager) Send(ctx context.Context, candidate txmgr.TxCandidate) (
), nil
}
func (m *mockTxManager) Call(_ context.Context, _ ethereum.CallMsg, _ *big.Int) ([]byte, error) {
if m.sendFails {
return nil, mockSendError
}
m.calls++
return []byte{}, nil
}
func (m *mockTxManager) BlockNumber(ctx context.Context) (uint64, error) {
panic("not implemented")
}
......@@ -57,6 +67,42 @@ func newTestFaultResponder(t *testing.T, sendFails bool) (*faultResponder, *mock
return responder, mockTxMgr
}
// TestResponder_CanResolve_CallFails tests the [Responder.CanResolve] method
// bubbles up the error returned by the [txmgr.Call] method.
func TestResponder_CanResolve_CallFails(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t, true)
resolved := responder.CanResolve(context.Background())
require.False(t, resolved)
require.Equal(t, 0, mockTxMgr.sends)
}
// TestResponder_CanResolve_Success tests the [Responder.CanResolve] method
// succeeds when the call message is successfully sent through the txmgr.
func TestResponder_CanResolve_Success(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t, false)
resolved := responder.CanResolve(context.Background())
require.True(t, resolved)
require.Equal(t, 1, mockTxMgr.calls)
}
// TestResponder_Resolve_SendFails tests the [Responder.Resolve] method
// bubbles up the error returned by the [txmgr.Send] method.
func TestResponder_Resolve_SendFails(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t, true)
err := responder.Resolve(context.Background())
require.ErrorIs(t, err, mockSendError)
require.Equal(t, 0, mockTxMgr.sends)
}
// TestResponder_Resolve_Success tests the [Responder.Resolve] method
// succeeds when the tx candidate is successfully sent through the txmgr.
func TestResponder_Resolve_Success(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t, false)
err := responder.Resolve(context.Background())
require.NoError(t, err)
require.Equal(t, 1, mockTxMgr.sends)
}
// TestResponder_Respond_SendFails tests the [Responder.Respond] method
// bubbles up the error returned by the [txmgr.Send] method.
func TestResponder_Respond_SendFails(t *testing.T) {
......
......@@ -71,10 +71,13 @@ type StepData struct {
// AttemptStep determines what step should occur for a given leaf claim.
// An error will be returned if the claim is not at the max depth.
func (s *Solver) AttemptStep(claim Claim) (StepData, error) {
func (s *Solver) AttemptStep(claim Claim, agreeWithClaimLevel bool) (StepData, error) {
if claim.Depth() != s.gameDepth {
return StepData{}, errors.New("cannot step on non-leaf claims")
}
if agreeWithClaimLevel {
return StepData{}, errors.New("cannot step on claims we agree with")
}
claimCorrect, err := s.agreeWithClaim(claim.ClaimData)
if err != nil {
return StepData{}, err
......
......@@ -111,18 +111,29 @@ func TestAttemptStep(t *testing.T) {
},
}
step, err := solver.AttemptStep(bottom)
step, err := solver.AttemptStep(bottom, false)
require.NoError(t, err)
require.Equal(t, bottom, step.LeafClaim)
require.True(t, step.IsAttack)
require.Equal(t, step.PreState, BuildAlphabetPreimage(3, "d"))
_, err = solver.AttemptStep(middle)
_, err = solver.AttemptStep(middle, false)
require.Error(t, err)
step, err = solver.AttemptStep(zero)
step, err = solver.AttemptStep(zero, false)
require.NoError(t, err)
require.Equal(t, zero, step.LeafClaim)
require.True(t, step.IsAttack)
require.Equal(t, canonicalProvider.AbsolutePreState(), step.PreState)
}
func TestAttempStep_AgreeWithClaimLevel_Fails(t *testing.T) {
maxDepth := 3
canonicalProvider := NewAlphabetProvider("abcdefgh", uint64(maxDepth))
solver := NewSolver(maxDepth, canonicalProvider)
_, _, middle, _ := createTestClaims()
step, err := solver.AttemptStep(middle, true)
require.Error(t, err)
require.Equal(t, StepData{}, step)
}
......@@ -38,6 +38,11 @@ var (
Usage: "Temporary hardcoded flag if we agree or disagree with the proposed output.",
EnvVars: prefixEnvVars("AGREE_WITH_PROPOSED_OUTPUT"),
}
GameDepthFlag = &cli.IntFlag{
Name: "game-depth",
Usage: "Depth of the game tree.",
EnvVars: prefixEnvVars("GAME_DEPTH"),
}
// Optional Flags
)
......@@ -47,6 +52,7 @@ var requiredFlags = []cli.Flag{
DGFAddressFlag,
AlphabetFlag,
AgreeWithProposedOutputFlag,
GameDepthFlag,
}
// optionalFlags is a list of unchecked cli flags
......
......@@ -4,7 +4,6 @@ set -euo pipefail
DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
cd "$DIR"
# build the challenger to keep it up to date
make
cd ..
......@@ -21,21 +20,17 @@ CHARLIE_KEY="74feb147d72bfae943e6b4e483410933d9e447d5dc47d52432dcc2c1454dabb7"
MALLORY_ADDRESS="0x4641c704a6c743f73ee1f36C7568Fbf4b80681e4"
MALLORY_KEY="28d7045146193f5f4eeb151c4843544b1b0d30a7ac1680c845a416fac65a7715"
echo "----------------------------------------------------------------"
echo " - Fetching balance of the sponsor"
echo " - Balance: $(cast balance 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266)"
echo "----------------------------------------------------------------"
echo "Funding Charlie"
cast send $CHARLIE_ADDRESS --value 5ether --private-key $DEVNET_SPONSOR
echo "Funding Mallory"
cast send $MALLORY_ADDRESS --value 5ether --private-key $DEVNET_SPONSOR
# Fault game type = 0
GAME_TYPE=0
# Root claim commits to the entire trace.
......@@ -45,8 +40,6 @@ ROOT_CLAIM=$(cast keccak $(cast abi-encode "f(uint256,uint256)" 15 122))
# Doesn't matter right now since we're not deleting outputs, so just set it to 1
EXTRA_DATA=$(cast to-bytes32 1)
echo "Initializing the game"
cast call --private-key $MALLORY_KEY $DISPUTE_GAME_PROXY "create(uint8,bytes32,bytes)" $GAME_TYPE $ROOT_CLAIM $EXTRA_DATA
cast send --private-key $MALLORY_KEY $DISPUTE_GAME_PROXY "create(uint8,bytes32,bytes)" $GAME_TYPE $ROOT_CLAIM $EXTRA_DATA
#!/bin/bash
set -euo pipefail
DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
cd "$DIR"
......@@ -15,4 +14,11 @@ MALLORY_KEY="28d7045146193f5f4eeb151c4843544b1b0d30a7ac1680c845a416fac65a7715"
FAULT_GAME_ADDRESS="0x8daf17a20c9dba35f005b6324f493785d239719d"
./bin/op-challenger --l1-eth-rpc http://localhost:8545 --alphabet "abcdexyz" --game-address $FAULT_GAME_ADDRESS --private-key $MALLORY_KEY --num-confirmations 1 --agree-with-proposed-output=false
./bin/op-challenger \
--l1-eth-rpc http://localhost:8545 \
--alphabet "abcdexyz" \
--game-address $FAULT_GAME_ADDRESS \
--private-key $MALLORY_KEY \
--num-confirmations 1 \
--game-depth 4 \
--agree-with-proposed-output=false
......@@ -44,6 +44,9 @@ type fakeTxMgr struct {
func (f fakeTxMgr) From() common.Address {
return f.from
}
func (f fakeTxMgr) Call(_ context.Context, _ ethereum.CallMsg, _ *big.Int) ([]byte, error) {
panic("unimplemented")
}
func (f fakeTxMgr) BlockNumber(_ context.Context) (uint64, error) {
panic("unimplemented")
}
......
......@@ -5,7 +5,7 @@ import (
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/stretchr/testify/require"
)
......@@ -29,7 +29,7 @@ func TestTimeTravel(t *testing.T) {
// It should be able to jump straight to the new time with just a single block
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)
defer cancel()
err = e2eutils.WaitFor(ctx, time.Second, func() (bool, error) {
err = utils.WaitFor(ctx, time.Second, func() (bool, error) {
postTravel, err := l1Client.BlockByNumber(context.Background(), nil)
if err != nil {
return false, err
......
......@@ -8,7 +8,6 @@ import (
"math/big"
"time"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
......@@ -19,6 +18,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
)
var MessagePassedTopic = crypto.Keccak256Hash([]byte("MessagePassed(uint256,address,address,uint256,uint256,bytes,bytes32)"))
......@@ -36,7 +36,7 @@ func WaitForOutputRootPublished(ctx context.Context, client *ethclient.Client, p
}
getL2BlockFromLatestOutput := func() (*big.Int, error) { return l2OO.LatestBlockNumber(opts) }
outputBlockNum, err := e2eutils.WaitAndGet[*big.Int](ctx, time.Second, getL2BlockFromLatestOutput, func(latest *big.Int) bool {
outputBlockNum, err := utils.WaitAndGet[*big.Int](ctx, time.Second, getL2BlockFromLatestOutput, func(latest *big.Int) bool {
return latest.Cmp(l2BlockNumber) >= 0
})
if err != nil {
......@@ -72,7 +72,7 @@ func WaitForFinalizationPeriod(ctx context.Context, client *ethclient.Client, po
// Assume clock is relatively correct
time.Sleep(time.Until(targetTime))
// Poll for L1 Block to have a time greater than the target time
return e2eutils.WaitFor(ctx, time.Second, func() (bool, error) {
return utils.WaitFor(ctx, time.Second, func() (bool, error) {
header, err := client.HeaderByNumber(ctx, nil)
if err != nil {
return false, fmt.Errorf("retrieve latest header: %w", err)
......
package e2eutils
package utils
import (
"context"
......
......@@ -4,9 +4,12 @@ package mocks
import (
context "context"
big "math/big"
common "github.com/ethereum/go-ethereum/common"
ethereum "github.com/ethereum/go-ethereum"
mock "github.com/stretchr/testify/mock"
txmgr "github.com/ethereum-optimism/optimism/op-service/txmgr"
......@@ -43,6 +46,32 @@ func (_m *TxManager) BlockNumber(ctx context.Context) (uint64, error) {
return r0, r1
}
// Call provides a mock function with given fields: ctx, msg, blockNumber
func (_m *TxManager) Call(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
ret := _m.Called(ctx, msg, blockNumber)
var r0 []byte
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg, *big.Int) ([]byte, error)); ok {
return rf(ctx, msg, blockNumber)
}
if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg, *big.Int) []byte); ok {
r0 = rf(ctx, msg, blockNumber)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]byte)
}
}
if rf, ok := ret.Get(1).(func(context.Context, ethereum.CallMsg, *big.Int) error); ok {
r1 = rf(ctx, msg, blockNumber)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// From provides a mock function with given fields:
func (_m *TxManager) From() common.Address {
ret := _m.Called()
......
......@@ -45,6 +45,10 @@ type TxManager interface {
// NOTE: Send can be called concurrently, the nonce will be managed internally.
Send(ctx context.Context, candidate TxCandidate) (*types.Receipt, error)
// Call is used to call a contract.
// Internally, it uses the [ethclient.Client.CallContract] method.
Call(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error)
// From returns the sending address associated with the instance of the transaction manager.
// It is static for a single instance of a TxManager.
From() common.Address
......@@ -59,6 +63,9 @@ type ETHBackend interface {
// BlockNumber returns the most recent block number.
BlockNumber(ctx context.Context) (uint64, error)
// CallContract executes an eth_call against the provided contract.
CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error)
// TransactionReceipt queries the backend for a receipt associated with
// txHash. If lookup does not fail, but the transaction is not found,
// nil should be returned for both values.
......@@ -155,6 +162,12 @@ func (m *SimpleTxManager) Send(ctx context.Context, candidate TxCandidate) (*typ
return receipt, err
}
// Call is used to call a contract.
// Internally, it uses the [ethclient.Client.CallContract] method.
func (m *SimpleTxManager) Call(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
return m.backend.CallContract(ctx, msg, blockNumber)
}
// send performs the actual transaction creation and sending.
func (m *SimpleTxManager) send(ctx context.Context, candidate TxCandidate) (*types.Receipt, error) {
if m.cfg.TxSendTimeout != 0 {
......
......@@ -194,6 +194,11 @@ func (b *mockBackend) BlockNumber(ctx context.Context) (uint64, error) {
return b.blockHeight, nil
}
// Call mocks a call to the EVM.
func (b *mockBackend) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
return nil, nil
}
func (b *mockBackend) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
return &types.Header{
BaseFee: b.g.basefee(),
......@@ -649,6 +654,10 @@ func (b *failingBackend) HeaderByNumber(_ context.Context, _ *big.Int) (*types.H
}, nil
}
func (b *failingBackend) CallContract(_ context.Context, _ ethereum.CallMsg, _ *big.Int) ([]byte, error) {
return nil, errors.New("unimplemented")
}
func (b *failingBackend) SendTransaction(_ context.Context, _ *types.Transaction) error {
return errors.New("unimplemented")
}
......
......@@ -10,6 +10,7 @@
},
"scripts": {
"clean": "npx nx run-many --target=clean",
"bindings": "nx bindings @eth-optimism/contracts-bedrock",
"build": "npx nx run-many --target=build",
"test": "npx nx run-many --target=test",
"lint": "npx nx run-many --target=lint",
......
......@@ -44,7 +44,7 @@
"l1GenesisBlockTimestamp": "0x64935846",
"l1StartingBlockTag": "earliest",
"l2GenesisRegolithTimeOffset": "0x0",
"faultGameAbsolutePrestate": 140,
"faultGameAbsolutePrestate": 96,
"faultGameMaxDepth": 4,
"faultGameMaxDuration": 604800
}
\ No newline at end of file
......@@ -9,8 +9,10 @@
"contracts/**/*.sol"
],
"scripts": {
"bindings": "cd ../../op-bindings && make",
"build": "npx nx build:contracts",
"bindings": "pnpm bindings:ts && pnpm bindings:go",
"bindings:ts": "pnpm generate:addresses && nx generate @eth-optimism/contracts-ts",
"bindings:go": "cd ../../op-bindings && make",
"build": "nx build:contracts",
"prebuild:contracts": "./scripts/verify-foundry-install.sh",
"build:contracts": "pnpm build:forge",
"build:forge": "forge build",
......
artifacts
cache
typechain
.deps
.envrc
.env
/dist/
coverage
artifacts
cache
typechain
.deps
.envrc
.env
/dist/
module.exports = {
...require('../../.prettierrc.js'),
}
# Code gen
Summary -
- This package is generated from [contracts-bedrock](../contracts-bedrock/)
- It's version is kept in sync with contracts bedrock via the [changeset config](../../.changeset/config.json) e.g. if contracts-bedrock is `4.2.0` this package will have the same version.
## Code gen instructions
To run the code gen run the `generate` script from [package.json](./package.json). Make sure node modules is installed.
```bash
pnpm i && pnpm generate
```
MIT License
Copyright (c) 2022 Optimism
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
## Contracts TS
[![codecov](https://codecov.io/gh/ethereum-optimism/optimism/branch/develop/graph/badge.svg?token=0VTG7PG7YR&flag=contracts-bedrock-tests)](https://codecov.io/gh/ethereum-optimism/optimism)
ABI and Address constants + generated code from [@eth-optimism/contracts-bedrock/](../contracts-bedrock/) for use in TypeScript.
Much of this package is generated. See [CODE_GEN.md](./CODE_GEN.md) for instructions on how to generate.
#### @eth-optimism/contracts-ts
The main entrypoint exports constants related to contracts bedrock as const. As const allows it to be [used in TypeScript with stronger typing than importing JSON](https://github.com/microsoft/TypeScript/issues/32063).
- Exports contract abis.
- Exports contract addresses
```typescript
import {
l2OutputOracleProxyABI,
l2OutputOracleAddresses,
} from '@eth-optimism/contracts-ts'
console.log(l2OutputOracleAddresses[10], abi)
```
Addresses are also exported as an object for convenience.
```typescript
import { addresses } from '@eth-optimism/contracts-ts'
console.log(addresses.l2OutputOracle[10])
```
#### @eth-optimism/contracts-ts/react
- All [React hooks](https://wagmi.sh/cli/plugins/react) `@eth-optimism/contracts-ts/react`
```typescript
import { useAddressManagerAddress } from '@eth-optimism/contracts-ts/react'
const component = () => {
const { data, error, loading } = useAddressManagerAddress()
if (loading) {
return <div>Loading</div>
}
if (err) {
return <div>Error</div>
}
return <div>{data}</div>
}
```
#### @eth-optimism/contracts-ts/actions
- All [wagmi actions](https://wagmi.sh/react/actions) for use in Vanilla JS or non react code
```typescript
import { readSystemConfig } from '@eth-optimism/contracts-ts/actions'
console.log(await readSystemConfig())
```
#### See Also
- [Contracts bedrock specs](../../specs/)
- [Wagmi](https://wagmi.sh)
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"AddressManager": {
"1": "0xdE1FCfB0851916CA5101820A69b13a4E276bd81F",
"5": "0xa6f73589243a6A7a9023b1Fa0651b1d89c177111"
},
"AssetReceiver": {
"1": "0x15DdA60616Ffca20371ED1659dBB78E888f65556",
"10": "0x15DdA60616Ffca20371ED1659dBB78E888f65556"
},
"CheckBalanceHigh": {
"1": "0x7eC64a8a591bFf829ff6C8be76074D540ACb813F",
"5": "0x7eC64a8a591bFf829ff6C8be76074D540ACb813F",
"420": "0x5d7103853f12109A7d27F118e54BbC654ad847E9"
},
"CheckBalanceLow": {
"1": "0x381a4eFC2A2C914eA1889722bB4B44Fa6BD5b640",
"5": "0x381a4eFC2A2C914eA1889722bB4B44Fa6BD5b640",
"420": "0x7Ce13D154FAEE5C8B3E6b19d4Add16f21d884474"
},
"CheckGelatoLow": {
"1": "0x4f7CFc43f6D262a085F3b946cAC69E7a8E39BBAa",
"5": "0x4f7CFc43f6D262a085F3b946cAC69E7a8E39BBAa",
"420": "0xF9c8a4Cb4021f57F9f6d69799cA9BefF64524862"
},
"CheckTrue": {
"1": "0x5c741a38cb11424711231777D71689C458eE835D",
"5": "0x5c741a38cb11424711231777D71689C458eE835D",
"420": "0x47443D0C184e022F19BD1578F5bca6B8a9F58E32"
},
"Drippie": {
"1": "0x44b3A2a040057eBafC601A78647e805fd58B1f50"
},
"Drippie_goerli": {
"5": "0x44b3A2a040057eBafC601A78647e805fd58B1f50"
},
"Drippie_optimism-goerli": {
"420": "0x8D8d533C16D23847EB04EEB0925be8900Dd3af86"
},
"L1CrossDomainMessenger": {
"1": "0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1",
"5": "0x5086d1eEF304eb5284A0f6720f79403b4e9bE294"
},
"L1ERC721Bridge": {
"1": "0x5a7749f83b81B301cAb5f48EB8516B986DAef23D",
"5": "0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9"
},
"L1StandardBridge": {
"1": "0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1",
"5": "0x636Af16bf2f682dD3109e60102b8E1A089FedAa8"
},
"L2OutputOracle": {
"1": "0xdfe97868233d1aa22e815a266982f2cf17685a27",
"5": "0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0"
},
"OptimismMintableERC20Factory": {
"1": "0x4200000000000000000000000000000000000012",
"5": "0x4200000000000000000000000000000000000012",
"420": "0x4200000000000000000000000000000000000012"
},
"OptimismPortal": {
"1": "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed",
"5": "0x5b47E1A08Ea6d985D6649300584e6722Ec4B1383"
},
"PortalSender": {
"1": "0x0A893d9576b9cFD9EF78595963dc973238E78210",
"5": "0xe7FACd39531ee3C313330E93B4d7a8B8A3c84Aa4"
},
"ProxyAdmin": {
"1": "0x4200000000000000000000000000000000000018",
"5": "0x4200000000000000000000000000000000000018"
},
"SystemConfig": {
"1": "0x229047fed2591dbec1eF1118d64F7aF3dB9EB290",
"5": "0xAe851f927Ee40dE99aaBb7461C00f9622ab91d60"
},
"SystemDictator": {
"1": "0xB4453CEb33d2e67FA244A24acf2E50CEF31F53cB"
},
"SystemDictator_goerli": {
"5": "0x1f0613A44c9a8ECE7B3A2e0CdBdF0F5B47A50971"
},
"TeleportrWithdrawer": {
"1": "0x78A25524D90E3D0596558fb43789bD800a5c3007"
},
"AttestationStation": {
"10": "0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77",
"420": "0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77"
},
"L2ERC721Bridge": {
"10": "0x4200000000000000000000000000000000000014",
"420": "0x4200000000000000000000000000000000000014"
},
"MintManager": {
"10": "0x5C4e7Ba1E219E47948e6e3F55019A647bA501005",
"420": "0x038a8825A3C3B0c08d52Cc76E5E361953Cf6Dc76"
},
"OptimismMintableERC721Factory": {
"10": "0x4200000000000000000000000000000000000017"
},
"OptimismMintableERC721Factory_optimism-goerli": {
"420": "0x4200000000000000000000000000000000000017"
},
"Optimist": {
"10": "0x2335022c740d17c2837f9C884Bfe4fFdbf0A95D5",
"420": "0x2335022c740d17c2837f9C884Bfe4fFdbf0A95D5"
},
"OptimistAllowlist": {
"10": "0x482b1945D58f2E9Db0CEbe13c7fcFc6876b41180",
"420": "0x482b1945D58f2E9Db0CEbe13c7fcFc6876b41180"
},
"OptimistInviter": {
"10": "0x073031A1E1b8F5458Ed41Ce56331F5fd7e1de929",
"420": "0x073031A1E1b8F5458Ed41Ce56331F5fd7e1de929"
},
"BaseFeeVault": {
"420": "0x4200000000000000000000000000000000000019"
},
"GasPriceOracle": {
"420": "0x420000000000000000000000000000000000000F"
},
"L1Block": {
"420": "0x4200000000000000000000000000000000000015"
},
"L1FeeVault": {
"420": "0x420000000000000000000000000000000000001a"
},
"L2CrossDomainMessenger": {
"420": "0x4200000000000000000000000000000000000007"
},
"L2StandardBridge": {
"420": "0x4200000000000000000000000000000000000010"
},
"L2ToL1MessagePasser": {
"420": "0x4200000000000000000000000000000000000016"
},
"SequencerFeeVault": {
"420": "0x4200000000000000000000000000000000000011"
}
}
VITE_RPC_URL_L2_GOERLI=
VITE_RPC_URL_L2_MAINNET=
VITE_RPC_URL_L1_GOERLI=
VITE_RPC_URL_L1_MAINNET=
{
"name": "@eth-optimism/contracts-ts",
"version": "0.15.0",
"description": "TypeScript interface for Contracts Bedrock",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/ethereum-optimism/optimism.git",
"directory": "packages/contracts-ts"
},
"homepage": "https://optimism.io",
"type": "module",
"main": "dist/constants.js",
"module": "dist/constants.mjs",
"types": "src/constants.ts",
"exports": {
".": {
"types": "./src/constants.ts",
"import": "./dist/constants.js",
"require": "./dist/constants.cjs"
},
"./actions": {
"types": "./src/actions.ts",
"import": "./dist/actions.js",
"require": "./dist/actions.cjs"
},
"./react": {
"types": "./src/react.ts",
"import": "./dist/react.js",
"require": "./dist/react.cjs"
}
},
"files": [
"dist/",
"src/"
],
"scripts": {
"build": "tsup",
"generate": "wagmi generate && pnpm build && pnpm lint:fix",
"generate:check": "pnpm generate && git diff --exit-code ./addresses.json && git diff --exit-code ./abis.json",
"lint": "prettier --check .",
"lint:fix": "prettier --write .",
"test": "vitest",
"test:coverage": "vitest run --coverage",
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"@eth-optimism/contracts-bedrock": "workspace:*",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react-hooks": "^8.0.1",
"@types/glob": "^8.1.0",
"@vitest/coverage-istanbul": "^0.33.0",
"@wagmi/cli": "^1.3.0",
"@wagmi/core": "^1.3.8",
"abitype": "^0.9.2",
"glob": "^10.3.3",
"isomorphic-fetch": "^3.0.0",
"jest-dom": "link:@types/@testing-library/jest-dom",
"jsdom": "^22.1.0",
"tsup": "^7.1.0",
"typescript": "^5.1.6",
"vite": "^4.4.4",
"vitest": "^0.33.0"
},
"peerDependencies": {
"@wagmi/core": ">1.0.0",
"wagmi": ">1.0.0"
},
"peerDependenciesMeta": {
"wagmi": {
"optional": true
},
"@wagmi/core": {
"optional": true
}
},
"dependencies": {
"@testing-library/react": "^14.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"viem": "^1.3.0"
}
}
import fetch from 'isomorphic-fetch'
// viem needs this
global.fetch = fetch
This source diff could not be displayed because it is too large. You can view the blob instead.
import { test, expect } from 'vitest'
import { addresses } from './constants'
import { readFileSync } from 'fs'
import { join } from 'path'
const jsonAddresses = JSON.parse(
readFileSync(join(__dirname, '../addresses.json'), 'utf8')
)
test('should have generated addresses', () => {
expect(addresses).toEqual(jsonAddresses)
})
This source diff could not be displayed because it is too large. You can view the blob instead.
import matchers from '@testing-library/jest-dom/matchers'
import { cleanup, waitFor } from '@testing-library/react'
import { renderHook } from '@testing-library/react-hooks'
import { afterEach, expect, test } from 'vitest'
import { useMintManagerOwner } from './react'
import { configureChains, createConfig, WagmiConfig } from 'wagmi'
import * as React from 'react'
import { optimism } from 'viem/chains'
import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
expect.extend(matchers)
afterEach(() => {
cleanup()
})
const { publicClient } = configureChains(
[optimism],
[
jsonRpcProvider({
rpc: () => ({
http:
import.meta.env.VITE_RPC_URL_L2_MAINNET ??
'https://mainnet.optimism.io',
}),
}),
]
)
const config = createConfig({
publicClient: ({ chainId }) => publicClient({ chainId }),
})
const blockNumber = BigInt(106806163)
test('react hooks should work', async () => {
const hook = renderHook(
() => useMintManagerOwner({ chainId: 10, blockNumber }),
{
wrapper: ({ children }) => (
<WagmiConfig config={config}>{children}</WagmiConfig>
),
}
)
await waitFor(() => {
hook.rerender()
if (hook.result.current.error) throw hook.result.current.error
expect(hook.result.current?.data).toBeDefined()
})
const normalizedResult = {
...hook.result.current,
internal: {
...hook.result.current.internal,
dataUpdatedAt: 'SNAPSHOT_TEST_REMOVED!!!',
},
}
expect(normalizedResult).toMatchInlineSnapshot(`
{
"data": "0x2A82Ae142b2e62Cb7D10b55E323ACB1Cab663a26",
"error": null,
"fetchStatus": "idle",
"internal": {
"dataUpdatedAt": "SNAPSHOT_TEST_REMOVED!!!",
"errorUpdatedAt": 0,
"failureCount": 0,
"isFetchedAfterMount": true,
"isLoadingError": false,
"isPaused": false,
"isPlaceholderData": false,
"isPreviousData": false,
"isRefetchError": false,
"isStale": true,
"remove": [Function],
},
"isError": false,
"isFetched": true,
"isFetchedAfterMount": true,
"isFetching": false,
"isIdle": false,
"isLoading": false,
"isRefetching": false,
"isSuccess": true,
"refetch": [Function],
"status": "success",
}
`)
})
This source diff could not be displayed because it is too large. You can view the blob instead.
/// <reference types="vite/client" />
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"baseUrl": "./src",
"strict": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "node",
"jsx": "react",
"target": "ESNext",
"noEmit": true
},
"include": ["./src"]
}
import { defineConfig } from 'tsup'
import packageJson from './package.json'
export default defineConfig({
name: packageJson.name,
entry: ['src/constants.ts', 'src/actions.ts', 'src/react.ts'],
outDir: 'dist',
format: ['esm', 'cjs'],
splitting: false,
sourcemap: true,
clean: false,
})
import { defineConfig } from 'vitest/config'
// @see https://vitest.dev/config/
export default defineConfig({
test: {
setupFiles: './setupVitest.ts',
environment: 'jsdom',
coverage: {
provider: 'istanbul',
},
},
})
import { ContractConfig, defineConfig, Plugin } from '@wagmi/cli'
import { actions, react } from '@wagmi/cli/plugins'
import glob from 'glob'
import { readFileSync, writeFileSync } from 'fs'
import type { Abi, AbiFunction, Address } from 'abitype'
import { isDeepStrictEqual } from 'util'
/**
* Predeployed contract addresses
* In future it would be nice to have a json file in contracts bedrock be generated as source of truth
* Keep this in sync with op-bindings/predeploys/addresses.go in meantime
*/
const predeployContracts = {
LegacyMessagePasser: {
address: '0x4200000000000000000000000000000000000000',
introduced: 'Legacy',
deprecated: true,
proxied: true,
},
DeployerWhitelist: {
address: '0x4200000000000000000000000000000000000002',
introduced: 'Legacy',
deprecated: true,
proxied: true,
},
LegacyERC20ETH: {
address: '0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000',
introduced: 'Legacy',
deprecated: true,
proxied: false,
},
WETH9: {
address: '0x4200000000000000000000000000000000000006',
introduced: 'Legacy',
deprecated: false,
proxied: false,
},
L2CrossDomainMessenger: {
address: '0x4200000000000000000000000000000000000007',
introduced: 'Legacy',
deprecated: false,
proxied: true,
},
L2StandardBridge: {
address: '0x4200000000000000000000000000000000000010',
introduced: 'Legacy',
deprecated: false,
proxied: true,
},
SequencerFeeVault: {
address: '0x4200000000000000000000000000000000000011',
introduced: 'Legacy',
deprecated: false,
proxied: true,
},
OptimismMintableERC20Factory: {
address: '0x4200000000000000000000000000000000000012',
introduced: 'Legacy',
deprecated: false,
proxied: true,
},
L1BlockNumber: {
address: '0x4200000000000000000000000000000000000013',
introduced: 'Legacy',
deprecated: true,
proxied: true,
},
GasPriceOracle: {
address: '0x420000000000000000000000000000000000000F',
introduced: 'Legacy',
deprecated: false,
proxied: true,
},
GovernanceToken: {
address: '0x4200000000000000000000000000000000000042',
introduced: 'Legacy',
deprecated: false,
proxied: false,
},
L1Block: {
address: '0x4200000000000000000000000000000000000015',
introduced: 'Bedrock',
deprecated: false,
proxied: true,
},
L2ToL1MessagePasser: {
address: '0x4200000000000000000000000000000000000016',
introduced: 'Bedrock',
deprecated: false,
proxied: true,
},
L2ERC721Bridge: {
address: '0x4200000000000000000000000000000000000014',
introduced: 'Legacy',
deprecated: false,
proxied: true,
},
OptimismMintableERC721Factory: {
address: '0x4200000000000000000000000000000000000017',
introduced: 'Bedrock',
deprecated: false,
proxied: true,
},
ProxyAdmin: {
address: '0x4200000000000000000000000000000000000018',
introduced: 'Bedrock',
deprecated: false,
proxied: true,
},
BaseFeeVault: {
address: '0x4200000000000000000000000000000000000019',
introduced: 'Bedrock',
deprecated: false,
proxied: true,
},
L1FeeVault: {
address: '0x420000000000000000000000000000000000001a',
introduced: 'Bedrock',
deprecated: false,
proxied: true,
},
} as const
type DeploymentJson = {
abi: Abi
address: `0x${string}`
}
const chains = {
1: 'mainnet',
10: 'optimism-mainnet',
5: 'goerli',
420: 'optimism-goerli',
} as const
if (!glob.sync('node_modules/*').length) {
throw new Error(
'No node_modules found. Please run `pnpm install` before running this script'
)
}
const deployments = {
[1]: glob.sync(
`node_modules/@eth-optimism/contracts-bedrock/deployments/${chains[1]}/*.json`
),
[10]: glob.sync(
`node_modules/@eth-optimism/contracts-bedrock/deployments/${chains[10]}/*.json`
),
[5]: glob.sync(
`node_modules/@eth-optimism/contracts-bedrock/deployments/${chains[5]}/*.json`
),
[420]: glob.sync(
`node_modules/@eth-optimism/contracts-bedrock/deployments/${chains[420]}/*.json`
),
}
Object.entries(deployments).forEach(([chain, deploymentFiles]) => {
if (deploymentFiles.length === 0) {
throw new Error(`No bedrock deployments found for ${chains[chain]}`)
}
})
const getWagmiContracts = (deploymentFiles: string[]) =>
deploymentFiles.map((artifactPath) => {
const deployment = JSON.parse(
readFileSync(artifactPath, 'utf8')
) as DeploymentJson
// There is a wagmi bug we need to filter out the MESSENGER method because it collides with messenger
// @see https://github.com/wagmi-dev/wagmi/issues/2724
const filterOut = new Set([
'MESSENGER',
'OTHER_BRIDGE',
'VERSION',
'DECIMALS',
])
const abi = deployment.abi.filter(
(item) => !filterOut.has((item as AbiFunction).name)
)
const contractConfig = {
abi,
name: artifactPath.split('/').reverse()[0]?.replace('.json', ''),
address: deployment.address,
} satisfies ContractConfig
if (!contractConfig.name) {
throw new Error(
'Unable to identify the name of the contract at ' + artifactPath
)
}
return contractConfig
})
/**
* Returns the contracts for the wagmi cli config
*/
const getContractConfigs = () => {
const contracts = {
1: getWagmiContracts(deployments[1]),
10: getWagmiContracts(deployments[10]),
5: getWagmiContracts(deployments[5]),
420: getWagmiContracts(deployments[420]),
}
const allContracts = Object.values(contracts).flat()
const config: ContractConfig[] = []
// this for loop is not terribly efficient but seems fast enough for the scale here
for (const contract of allContracts) {
// we will only process the implementation ABI but will use teh proxy addresses for deployments
const isProxy = contract.name.endsWith('Proxy')
// once we see the first deployment of a contract we will process all networks all at once
const alreadyProcessedContract = config.find(
(c) => c.name === contract.name
)
if (isProxy || alreadyProcessedContract) {
continue
}
const implementations = {
// @warning Later code assumes mainnet is first!!!
[1]: contracts[1].find((c) => c.name === contract.name),
// @warning Later code assumes mainnet is first!!!
[10]: contracts[10].find((c) => c.name === contract.name),
[5]: contracts[5].find((c) => c.name === contract.name),
[420]: contracts[420].find((c) => c.name === contract.name),
}
const maybeProxyName = contract.name + 'Proxy'
const proxies = {
// @warning Later code assumes mainnet is first!!!
[1]: contracts[1].find((c) => c.name === maybeProxyName),
// @warning Later code assumes mainnet is first!!!
[10]: contracts[10].find((c) => c.name === maybeProxyName),
[5]: contracts[5].find((c) => c.name === maybeProxyName),
[420]: contracts[420].find((c) => c.name === maybeProxyName),
}
const predeploy = predeployContracts[
contract.name as keyof typeof predeployContracts
] as { address: Address } | undefined
// If the contract has different abis on different networks we don't want to group them as a single abi
const isContractUnique = !Object.values(implementations).some(
(implementation) =>
implementation && !isDeepStrictEqual(implementation.abi, contract.abi)
)
if (!isContractUnique) {
Object.entries(implementations)
.filter(([_, implementation]) => implementation)
.forEach(([chain, implementation], i) => {
if (implementation) {
// make the first one cannonical. This will be mainnet or op mainnet if they exist
const name =
i === 0 ? contract.name : `${contract.name}_${chains[chain]}`
const nextConfig = {
abi: implementation.abi,
name,
address: {
[Number.parseInt(chain)]:
predeploy?.address ??
proxies[chain]?.address ??
implementation?.address,
}, // predeploy?.address ?? proxies[chain]?.address ?? implementation?.address
} satisfies ContractConfig
config.push(nextConfig)
}
})
continue
}
const wagmiConfig = {
abi: contract.abi,
name: contract.name,
address: {},
} satisfies ContractConfig
Object.entries(implementations).forEach(([chain, proxy]) => {
if (proxy) {
wagmiConfig.address[chain] =
predeploy?.address ?? proxy.address ?? contract.address
}
})
// if proxies exist overwrite the address with the proxy address
Object.entries(proxies).forEach(([chain, proxy]) => {
if (proxy) {
wagmiConfig.address[chain] = predeploy?.address ?? proxy.address
}
})
config.push(wagmiConfig)
}
return config
}
/**
* This plugin will create a addresses mapping from contract name to address
*/
const addressesByContractByNetworkPlugin: Plugin = {
name: 'addressesByContractByNetwork',
run: async ({ contracts }) => {
const addresses = Object.fromEntries(
contracts.map((contract) => [contract.name, contract.address ?? {}])
)
// write to json file so it's easy to audit in prs relative to the generated file diff
writeFileSync('./addresses.json', JSON.stringify(addresses, null, 2))
return {
content: [
`export const addresses = ${JSON.stringify(addresses)} as const`,
`export const predeploys = ${JSON.stringify(predeployContracts)}`,
].join('\n'),
}
},
}
/**
* This plugin will create an abi mapping from contract name to abi
*/
const abiPlugin: Plugin = {
name: 'abisByContractByNetwork',
run: async ({ contracts }) => {
const abis = Object.fromEntries(
contracts.map((contract) => [contract.name, contract.abi])
)
// write to json file so it's easy to audit in prs relative to the generated file diff
writeFileSync('./abis.json', JSON.stringify(abis, null, 2))
return {
content: `export const abis = ${JSON.stringify(abis)} as const`,
}
},
}
/**
* This plugin adds an eslint ignore to the generated code
*/
const eslintIgnorePlugin: Plugin = {
name: 'eslintIgnore',
run: async () => {
return {
prepend: `/* eslint-disable */`,
content: ``,
}
},
}
const contracts = getContractConfigs()
// @see https://wagmi.sh/cli
export default defineConfig([
{
out: 'src/constants.ts',
contracts,
plugins: [
eslintIgnorePlugin,
addressesByContractByNetworkPlugin,
abiPlugin,
],
},
{
out: 'src/actions.ts',
contracts,
plugins: [eslintIgnorePlugin, actions()],
},
{
out: 'src/react.ts',
contracts,
plugins: [eslintIgnorePlugin, react()],
},
])
// public rpcs are heavily throttled/rate limited so replace these with rpcs with apikeys. These are meant to be testnet rpcs
// in future these will get renamed to VITE_E2E_RPC_URL_GOERLI etc.
VITE_E2E_RPC_URL_L1=https://ethereum-goerli.publicnode.com
VITE_E2E_RPC_URL_L2=https://goerli.optimism.io
\ No newline at end of file
......@@ -326,13 +326,11 @@ export class CrossChainMessenger {
* Transforms a legacy message into its corresponding Bedrock representation.
*
* @param message Legacy message to transform.
* @param messageIndex The index of the message, if multiple exist from multicall
* @returns Bedrock representation of the message.
*/
public async toBedrockCrossChainMessage(
message: MessageLike,
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
): Promise<CrossChainMessage> {
const resolved = await this.toCrossChainMessage(message, messageIndex)
......@@ -376,13 +374,11 @@ export class CrossChainMessenger {
* L2ToL1MessagePasser contract on L2.
*
* @param message Message to transform.
* @param messageIndex The index of the message, if multiple exist from multicall
* @return Transformed message.
*/
public async toLowLevelMessage(
message: MessageLike,
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
): Promise<LowLevelMessage> {
const resolved = await this.toCrossChainMessage(message, messageIndex)
......@@ -586,13 +582,11 @@ export class CrossChainMessenger {
* create an entire CrossChainProvider object.
*
* @param message MessageLike to resolve into a CrossChainMessage.
* @param messageIndex The index of the message, if multiple exist from multicall
* @returns Message coerced into a CrossChainMessage.
*/
public async toCrossChainMessage(
message: MessageLike,
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
): Promise<CrossChainMessage> {
if (!message) {
......@@ -651,18 +645,25 @@ export class CrossChainMessenger {
* Retrieves the status of a particular message as an enum.
*
* @param message Cross chain message to check the status of.
* @param messageIndex The index of the message, if multiple exist from multicall
* @param fromBlockOrBlockHash The start block to use for the query filter on the RECEIVING chain
* @param toBlockOrBlockHash The end block to use for the query filter on the RECEIVING chain
* @returns Status of the message.
*/
public async getMessageStatus(
message: MessageLike,
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
// consider making this an options object next breaking release
messageIndex = 0,
fromBlockOrBlockHash?: BlockTag,
toBlockOrBlockHash?: BlockTag
): Promise<MessageStatus> {
const resolved = await this.toCrossChainMessage(message, messageIndex)
const receipt = await this.getMessageReceipt(resolved, messageIndex)
const receipt = await this.getMessageReceipt(
resolved,
messageIndex,
fromBlockOrBlockHash,
toBlockOrBlockHash
)
if (resolved.direction === MessageDirection.L1_TO_L2) {
if (receipt === null) {
......@@ -697,7 +698,6 @@ export class CrossChainMessenger {
await this.contracts.l1.OptimismPortal.provenWithdrawals(
hashLowLevelMessage(withdrawal)
)
// If the withdrawal hash has not been proven on L1,
// return `READY_TO_PROVE`
if (provenWithdrawal.timestamp.eq(BigNumber.from(0))) {
......@@ -742,16 +742,17 @@ export class CrossChainMessenger {
* Finds the receipt of the transaction that executed a particular cross chain message.
*
* @param message Message to find the receipt of.
* @param messageIndex The index of the message, if multiple exist from multicall
* @param fromBlockOrBlockHash The start block to use for the query filter on the RECEIVING chain
* @param toBlockOrBlockHash The end block to use for the query filter on the RECEIVING chain
* @returns CrossChainMessage receipt including receipt of the transaction that relayed the
* given message.
*/
public async getMessageReceipt(
message: MessageLike,
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
messageIndex = 0,
fromBlockOrBlockHash?: BlockTag,
toBlockOrHash?: BlockTag
): Promise<MessageReceipt> {
const resolved = await this.toCrossChainMessage(message, messageIndex)
// legacy withdrawals relayed prebedrock are v1
......@@ -783,10 +784,14 @@ export class CrossChainMessenger {
// this is safe because we can guarantee only one of these filters max will return something
const relayedMessageEvents = [
...(await messenger.queryFilter(
messenger.filters.RelayedMessage(messageHashV0)
messenger.filters.RelayedMessage(messageHashV0),
fromBlockOrBlockHash,
toBlockOrHash
)),
...(await messenger.queryFilter(
messenger.filters.RelayedMessage(messageHashV1)
messenger.filters.RelayedMessage(messageHashV1),
fromBlockOrBlockHash,
toBlockOrHash
)),
]
......@@ -806,10 +811,14 @@ export class CrossChainMessenger {
// FailedRelayedMessage events instead.
const failedRelayedMessageEvents = [
...(await messenger.queryFilter(
messenger.filters.FailedRelayedMessage(messageHashV0)
messenger.filters.FailedRelayedMessage(messageHashV0),
fromBlockOrBlockHash,
toBlockOrHash
)),
...(await messenger.queryFilter(
messenger.filters.FailedRelayedMessage(messageHashV1)
messenger.filters.FailedRelayedMessage(messageHashV1),
fromBlockOrBlockHash,
toBlockOrHash
)),
]
......@@ -846,12 +855,17 @@ export class CrossChainMessenger {
* @param opts.confirmations Number of transaction confirmations to wait for before returning.
* @param opts.pollIntervalMs Number of milliseconds to wait between polling for the receipt.
* @param opts.timeoutMs Milliseconds to wait before timing out.
* @param opts.fromBlockOrBlockHash The start block to use for the query filter on the RECEIVING chain
* @param opts.toBlockOrBlockHash The end block to use for the query filter on the RECEIVING chain
* @param messageIndex The index of the message, if multiple exist from multicall
* @returns CrossChainMessage receipt including receipt of the transaction that relayed the
* given message.
*/
public async waitForMessageReceipt(
message: MessageLike,
opts: {
fromBlockOrBlockHash?: BlockTag
toBlockOrHash?: BlockTag
confirmations?: number
pollIntervalMs?: number
timeoutMs?: number
......@@ -868,7 +882,12 @@ export class CrossChainMessenger {
let totalTimeMs = 0
while (totalTimeMs < (opts.timeoutMs || Infinity)) {
const tick = Date.now()
const receipt = await this.getMessageReceipt(resolved, messageIndex)
const receipt = await this.getMessageReceipt(
resolved,
messageIndex,
opts.fromBlockOrBlockHash,
opts.toBlockOrHash
)
if (receipt !== null) {
return receipt
} else {
......@@ -891,18 +910,19 @@ export class CrossChainMessenger {
* @param opts Options to pass to the waiting function.
* @param opts.pollIntervalMs Number of milliseconds to wait when polling.
* @param opts.timeoutMs Milliseconds to wait before timing out.
* @param opts.fromBlockOrBlockHash The start block to use for the query filter on the RECEIVING chain
* @param opts.toBlockOrBlockHash The end block to use for the query filter on the RECEIVING chain
* @param messageIndex The index of the message, if multiple exist from multicall
*/
public async waitForMessageStatus(
message: MessageLike,
status: MessageStatus,
opts: {
fromBlockOrBlockHash?: BlockTag
toBlockOrBlockHash?: BlockTag
pollIntervalMs?: number
timeoutMs?: number
} = {},
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
): Promise<void> {
// Resolving once up-front is slightly more efficient.
......@@ -911,7 +931,12 @@ export class CrossChainMessenger {
let totalTimeMs = 0
while (totalTimeMs < (opts.timeoutMs || Infinity)) {
const tick = Date.now()
const currentStatus = await this.getMessageStatus(resolved, messageIndex)
const currentStatus = await this.getMessageStatus(
resolved,
messageIndex,
opts.fromBlockOrBlockHash,
opts.toBlockOrBlockHash
)
// Handle special cases for L1 to L2 messages.
if (resolved.direction === MessageDirection.L1_TO_L2) {
......@@ -1018,18 +1043,25 @@ export class CrossChainMessenger {
* amount of time until the message will be picked up and executed on L2.
*
* @param message Message to estimate the time remaining for.
* @param messageIndex The index of the message, if multiple exist from multicall
* @param opts.fromBlockOrBlockHash The start block to use for the query filter on the RECEIVING chain
* @param opts.toBlockOrBlockHash The end block to use for the query filter on the RECEIVING chain
* @returns Estimated amount of time remaining (in seconds) before the message can be executed.
*/
public async estimateMessageWaitTimeSeconds(
message: MessageLike,
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
// consider making this an options object next breaking release
messageIndex = 0,
fromBlockOrBlockHash?: BlockTag,
toBlockOrBlockHash?: BlockTag
): Promise<number> {
const resolved = await this.toCrossChainMessage(message, messageIndex)
const status = await this.getMessageStatus(resolved, messageIndex)
const status = await this.getMessageStatus(
resolved,
messageIndex,
fromBlockOrBlockHash,
toBlockOrBlockHash
)
if (resolved.direction === MessageDirection.L1_TO_L2) {
if (
status === MessageStatus.RELAYED ||
......@@ -1134,14 +1166,11 @@ export class CrossChainMessenger {
* Returns the Bedrock output root that corresponds to the given message.
*
* @param message Message to get the Bedrock output root for.
* @param messageIndex The index of the message, if multiple exist from multicall
* @returns Bedrock output root.
*/
public async getMessageBedrockOutput(
message: MessageLike,
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
): Promise<BedrockOutputData | null> {
const resolved = await this.toCrossChainMessage(message, messageIndex)
......@@ -1190,14 +1219,11 @@ export class CrossChainMessenger {
* state root for the given message has not been published yet, this function returns null.
*
* @param message Message to find a state root for.
* @param messageIndex The index of the message, if multiple exist from multicall
* @returns State root for the block in which the message was created.
*/
public async getMessageStateRoot(
message: MessageLike,
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
): Promise<StateRoot | null> {
const resolved = await this.toCrossChainMessage(message, messageIndex)
......@@ -1380,14 +1406,11 @@ export class CrossChainMessenger {
* Generates the proof required to finalize an L2 to L1 message.
*
* @param message Message to generate a proof for.
* @param messageIndex The index of the message, if multiple exist from multicall
* @returns Proof that can be used to finalize the message.
*/
public async getMessageProof(
message: MessageLike,
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
): Promise<CrossChainMessageProof> {
const resolved = await this.toCrossChainMessage(message, messageIndex)
......@@ -1443,14 +1466,11 @@ export class CrossChainMessenger {
* Generates the bedrock proof required to finalize an L2 to L1 message.
*
* @param message Message to generate a proof for.
* @param messageIndex The index of the message, if multiple exist from multicall
* @returns Proof that can be used to finalize the message.
*/
public async getBedrockMessageProof(
message: MessageLike,
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
): Promise<BedrockCrossChainMessageProof> {
const resolved = await this.toCrossChainMessage(message, messageIndex)
......@@ -1585,6 +1605,7 @@ export class CrossChainMessenger {
* @param opts Additional options.
* @param opts.signer Optional signer to use to send the transaction.
* @param opts.overrides Optional transaction overrides.
* @param messageIndex The index of the message, if multiple exist from multicall
* @returns Transaction response for the finalization transaction.
*/
public async finalizeMessage(
......@@ -1593,9 +1614,6 @@ export class CrossChainMessenger {
signer?: Signer
overrides?: PayableOverrides
},
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
): Promise<TransactionResponse> {
return (opts?.signer || this.l1Signer).sendTransaction(
......@@ -1873,6 +1891,7 @@ export class CrossChainMessenger {
* @param message Message to generate the proving transaction for.
* @param opts Additional options.
* @param opts.overrides Optional transaction overrides.
* @param messageIndex The index of the message, if multiple exist from multicall
* @returns Transaction that can be signed and executed to prove the message.
*/
proveMessage: async (
......@@ -1880,9 +1899,6 @@ export class CrossChainMessenger {
opts?: {
overrides?: PayableOverrides
},
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
): Promise<TransactionRequest> => {
const resolved = await this.toCrossChainMessage(message, messageIndex)
......@@ -1932,6 +1948,7 @@ export class CrossChainMessenger {
* @param message Message to generate the finalization transaction for.
* @param opts Additional options.
* @param opts.overrides Optional transaction overrides.
* @param messageIndex The index of the message, if multiple exist from multicall
* @returns Transaction that can be signed and executed to finalize the message.
*/
finalizeMessage: async (
......@@ -1939,9 +1956,6 @@ export class CrossChainMessenger {
opts?: {
overrides?: PayableOverrides
},
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
): Promise<TransactionRequest> => {
const resolved = await this.toCrossChainMessage(message, messageIndex)
......@@ -2217,6 +2231,7 @@ export class CrossChainMessenger {
* @param message Message to generate the proving transaction for.
* @param opts Additional options.
* @param opts.overrides Optional transaction overrides.
* @param messageIndex The index of the message, if multiple exist from multicall
* @returns Gas estimate for the transaction.
*/
proveMessage: async (
......@@ -2224,9 +2239,6 @@ export class CrossChainMessenger {
opts?: {
overrides?: CallOverrides
},
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
): Promise<BigNumber> => {
return this.l1Provider.estimateGas(
......@@ -2240,6 +2252,7 @@ export class CrossChainMessenger {
* @param message Message to generate the finalization transaction for.
* @param opts Additional options.
* @param opts.overrides Optional transaction overrides.
* @param messageIndex The index of the message, if multiple exist from multicall
* @returns Gas estimate for the transaction.
*/
finalizeMessage: async (
......@@ -2247,9 +2260,6 @@ export class CrossChainMessenger {
opts?: {
overrides?: CallOverrides
},
/**
* The index of the withdrawal if multiple are made with multicall
*/
messageIndex = 0
): Promise<BigNumber> => {
return this.l1Provider.estimateGas(
......
......@@ -2,3 +2,4 @@
- The new tests for the next version of sdk will use vitest
- The vitest tests are kept here seperated from mocha tests for now
- Can find values needed in a `.env` file in `example.env`
......@@ -11,22 +11,40 @@ const crossChainMessenger = new CrossChainMessenger({
bedrock: true,
})
describe('prove message', () => {
describe('getMessageStatus', () => {
it(`should be able to correctly find a finalized withdrawal`, async () => {
/**
* Tx hash of legacy withdrawal that was claimed
* Tx hash of a withdrawal
*
* @see https://goerli-optimism.etherscan.io/tx/0xda9e9c8dfc7718bc1499e1e64d8df6cddbabc46e819475a6c755db286a41b9fa
* @see https://goerli-optimism.etherscan.io/tx/0x8fb235a61079f3fa87da66e78c9da075281bc4ba5f1af4b95197dd9480e03bb5
*/
const txWithdrawalHash =
'0xda9e9c8dfc7718bc1499e1e64d8df6cddbabc46e819475a6c755db286a41b9fa'
'0x8fb235a61079f3fa87da66e78c9da075281bc4ba5f1af4b95197dd9480e03bb5'
const txReceipt = await l2Provider.getTransactionReceipt(txWithdrawalHash)
expect(txReceipt).toBeDefined()
expect(await crossChainMessenger.getMessageStatus(txWithdrawalHash)).toBe(
MessageStatus.RELAYED
expect(
await crossChainMessenger.getMessageStatus(
txWithdrawalHash,
0,
9370789 - 1000,
9370789
)
).toBe(MessageStatus.RELAYED)
}, 20_000)
it(`should return READY_FOR_RELAY if not in block range`, async () => {
const txWithdrawalHash =
'0x8fb235a61079f3fa87da66e78c9da075281bc4ba5f1af4b95197dd9480e03bb5'
const txReceipt = await l2Provider.getTransactionReceipt(txWithdrawalHash)
expect(txReceipt).toBeDefined()
expect(
await crossChainMessenger.getMessageStatus(txWithdrawalHash, 0, 0, 0)
).toBe(MessageStatus.READY_FOR_RELAY)
}, 20_000)
})
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment