From fd1c86c1868f5977d4ed913d65831859a7139d9f Mon Sep 17 00:00:00 2001 From: Flocqst Date: Thu, 17 Aug 2023 09:03:25 +0200 Subject: [PATCH 01/59] remove unnecessary timer check from ListenAndServeContext --- op-service/httputil/server.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/op-service/httputil/server.go b/op-service/httputil/server.go index bc307cfea..80909ba37 100644 --- a/op-service/httputil/server.go +++ b/op-service/httputil/server.go @@ -14,15 +14,6 @@ func ListenAndServeContext(ctx context.Context, server *http.Server) error { errCh <- server.ListenAndServe() }() - // verify that the server comes up - tick := time.NewTimer(10 * time.Millisecond) - select { - case err := <-errCh: - return fmt.Errorf("http server failed: %w", err) - case <-tick.C: - break - } - select { case err := <-errCh: if errors.Is(err, http.ErrServerClosed) { From e2b717ecaa11cfdfb2c8cc8139e9551b398b0146 Mon Sep 17 00:00:00 2001 From: Flocqst Date: Thu, 17 Aug 2023 09:13:04 +0200 Subject: [PATCH 02/59] move op-node http package into op-service httputil + update related imports --- op-node/cmd/stateviz/main.go | 2 +- op-node/metrics/metrics.go | 2 +- op-node/node/server.go | 2 +- {op-node/http => op-service/httputil}/http.go | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename {op-node/http => op-service/httputil}/http.go (100%) diff --git a/op-node/cmd/stateviz/main.go b/op-node/cmd/stateviz/main.go index 3e721eb63..33049f889 100644 --- a/op-node/cmd/stateviz/main.go +++ b/op-node/cmd/stateviz/main.go @@ -18,7 +18,7 @@ import ( "sync" "time" - ophttp "github.com/ethereum-optimism/optimism/op-node/http" + ophttp "github.com/ethereum-optimism/optimism/op-service/httputil" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/log" ) diff --git a/op-node/metrics/metrics.go b/op-node/metrics/metrics.go index ec94f20dd..67cd740b0 100644 --- a/op-node/metrics/metrics.go +++ b/op-node/metrics/metrics.go @@ -10,7 +10,7 @@ import ( "strconv" "time" - ophttp "github.com/ethereum-optimism/optimism/op-node/http" + ophttp "github.com/ethereum-optimism/optimism/op-service/httputil" "github.com/ethereum-optimism/optimism/op-node/p2p/store" "github.com/ethereum-optimism/optimism/op-service/metrics" diff --git a/op-node/node/server.go b/op-node/node/server.go index ce18b667e..7908f38ac 100644 --- a/op-node/node/server.go +++ b/op-node/node/server.go @@ -7,7 +7,7 @@ import ( "net/http" "strconv" - ophttp "github.com/ethereum-optimism/optimism/op-node/http" + ophttp "github.com/ethereum-optimism/optimism/op-service/httputil" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rpc" diff --git a/op-node/http/http.go b/op-service/httputil/http.go similarity index 100% rename from op-node/http/http.go rename to op-service/httputil/http.go From 0a2ebc4996dbbf3de18902ee0f1495311c7bd3e5 Mon Sep 17 00:00:00 2001 From: Flocqst Date: Thu, 17 Aug 2023 09:52:42 +0200 Subject: [PATCH 03/59] modified package name and removed unused imports --- op-service/httputil/http.go | 2 +- op-service/httputil/server.go | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/op-service/httputil/http.go b/op-service/httputil/http.go index ff223ed29..8d15b9542 100644 --- a/op-service/httputil/http.go +++ b/op-service/httputil/http.go @@ -1,4 +1,4 @@ -package http +package httputil import ( "net/http" diff --git a/op-service/httputil/server.go b/op-service/httputil/server.go index 80909ba37..afab81e0e 100644 --- a/op-service/httputil/server.go +++ b/op-service/httputil/server.go @@ -3,9 +3,7 @@ package httputil import ( "context" "errors" - "fmt" "net/http" - "time" ) func ListenAndServeContext(ctx context.Context, server *http.Server) error { From 0f1633ece21a5fe0987279c86e632f27505a070b Mon Sep 17 00:00:00 2001 From: Flocqst Date: Thu, 17 Aug 2023 10:07:13 +0200 Subject: [PATCH 04/59] fix op-node-lint --- op-node/cmd/stateviz/main.go | 2 +- op-node/metrics/metrics.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/op-node/cmd/stateviz/main.go b/op-node/cmd/stateviz/main.go index 33049f889..847998436 100644 --- a/op-node/cmd/stateviz/main.go +++ b/op-node/cmd/stateviz/main.go @@ -18,8 +18,8 @@ import ( "sync" "time" - ophttp "github.com/ethereum-optimism/optimism/op-service/httputil" "github.com/ethereum-optimism/optimism/op-service/eth" + ophttp "github.com/ethereum-optimism/optimism/op-service/httputil" "github.com/ethereum/go-ethereum/log" ) diff --git a/op-node/metrics/metrics.go b/op-node/metrics/metrics.go index 67cd740b0..2ba8533d6 100644 --- a/op-node/metrics/metrics.go +++ b/op-node/metrics/metrics.go @@ -10,8 +10,8 @@ import ( "strconv" "time" - ophttp "github.com/ethereum-optimism/optimism/op-service/httputil" "github.com/ethereum-optimism/optimism/op-node/p2p/store" + ophttp "github.com/ethereum-optimism/optimism/op-service/httputil" "github.com/ethereum-optimism/optimism/op-service/metrics" pb "github.com/libp2p/go-libp2p-pubsub/pb" From 208731a6123c5e8f2b8595fe45a8bdd3d61dfcb9 Mon Sep 17 00:00:00 2001 From: Jason Yellick Date: Tue, 29 Aug 2023 12:58:35 -0400 Subject: [PATCH 05/59] Fix dangling modified file on make devnet-up When starting from a fresh clone of the repo and running ``` make make cannon-prestate make devnet-up ``` We are left with a file changed in the tree at ``` packages/contracts-bedrock/deploy-config/devnetL1.json ``` This file is a bit annoying as it should not be checked in but shows as an outstanding change. The python script reads the original file, backs it up, then rewrites that file with a new timestamp. I'm not entirely certain why the timestamp needs to be rewritten, so I've left that modification in place. Instead, this change takes the approach of moving the original file to a 'template' path, and ignoring the modified file. In this way there's no longer any need to constantly create a backup and have the changes show up in a git diff. --- bedrock-devnet/devnet/__init__.py | 26 ++++++++++++------- packages/contracts-bedrock/.gitignore | 3 +++ .../{devnetL1.json => devnetL1-template.json} | 0 3 files changed, 20 insertions(+), 9 deletions(-) rename packages/contracts-bedrock/deploy-config/{devnetL1.json => devnetL1-template.json} (100%) diff --git a/bedrock-devnet/devnet/__init__.py b/bedrock-devnet/devnet/__init__.py index f81460165..23972b0c9 100644 --- a/bedrock-devnet/devnet/__init__.py +++ b/bedrock-devnet/devnet/__init__.py @@ -56,8 +56,9 @@ def main(): deployment_dir = pjoin(contracts_bedrock_dir, 'deployments', 'devnetL1') op_node_dir = pjoin(args.monorepo_dir, 'op-node') ops_bedrock_dir = pjoin(monorepo_dir, 'ops-bedrock') - deploy_config_dir = pjoin(contracts_bedrock_dir, 'deploy-config'), - devnet_config_path = pjoin(contracts_bedrock_dir, 'deploy-config', 'devnetL1.json') + deploy_config_dir = pjoin(contracts_bedrock_dir, 'deploy-config') + devnet_config_path = pjoin(deploy_config_dir, 'devnetL1.json') + devnet_config_template_path = pjoin(deploy_config_dir, 'devnetL1-template.json') ops_chain_ops = pjoin(monorepo_dir, 'op-chain-ops') sdk_dir = pjoin(monorepo_dir, 'packages', 'sdk') @@ -69,6 +70,7 @@ def main(): l1_deployments_path=pjoin(deployment_dir, '.deploy'), deploy_config_dir=deploy_config_dir, devnet_config_path=devnet_config_path, + devnet_config_template_path=devnet_config_template_path, op_node_dir=op_node_dir, ops_bedrock_dir=ops_bedrock_dir, ops_chain_ops=ops_chain_ops, @@ -124,10 +126,16 @@ def deploy_contracts(paths): '--rpc-url', 'http://127.0.0.1:8545' ], env={}, cwd=paths.contracts_bedrock_dir) - +def init_devnet_l1_deploy_config(paths, update_timestamp=False): + deploy_config = read_json(paths.devnet_config_template_path) + if update_timestamp: + deploy_config['l1GenesisBlockTimestamp'] = '{:#x}'.format(int(time.time())) + write_json(paths.devnet_config_path, deploy_config) def devnet_l1_genesis(paths): log.info('Generating L1 genesis state') + init_devnet_l1_deploy_config(paths) + geth = subprocess.Popen([ 'geth', '--dev', '--http', '--http.api', 'eth,debug', '--verbosity', '4', '--gcmode', 'archive', '--dev.gaslimit', '30000000' @@ -157,13 +165,13 @@ def devnet_deploy(paths): if os.path.exists(paths.allocs_path) == False: devnet_l1_genesis(paths) - devnet_config_backup = pjoin(paths.devnet_dir, 'devnetL1.json.bak') - shutil.copy(paths.devnet_config_path, devnet_config_backup) - deploy_config = read_json(paths.devnet_config_path) - deploy_config['l1GenesisBlockTimestamp'] = '{:#x}'.format(int(time.time())) - write_json(paths.devnet_config_path, deploy_config) + # It's odd that we want to regenerate the devnetL1.json file with + # an updated timestamp different than the one used in the devnet_l1_genesis + # function. But, without it, CI flakes on this test rather consistently. + # If someone reads this comment and understands why this is being done, please + # update this comment to explain. + init_devnet_l1_deploy_config(paths, update_timestamp=True) outfile_l1 = pjoin(paths.devnet_dir, 'genesis-l1.json') - run_command([ 'go', 'run', 'cmd/main.go', 'genesis', 'l1', '--deploy-config', paths.devnet_config_path, diff --git a/packages/contracts-bedrock/.gitignore b/packages/contracts-bedrock/.gitignore index 60baa20be..d82f192d9 100644 --- a/packages/contracts-bedrock/.gitignore +++ b/packages/contracts-bedrock/.gitignore @@ -26,3 +26,6 @@ deployments/hardhat deployments/getting-started deployments/*/.deploy deployments/1337 + +# Devnet config which changes with each 'make devnet-up' +deploy-config/devnetL1.json diff --git a/packages/contracts-bedrock/deploy-config/devnetL1.json b/packages/contracts-bedrock/deploy-config/devnetL1-template.json similarity index 100% rename from packages/contracts-bedrock/deploy-config/devnetL1.json rename to packages/contracts-bedrock/deploy-config/devnetL1-template.json From 8bbd98d91a96adb76bec8f14a5928b488e45a11f Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Fri, 1 Sep 2023 13:10:29 +1000 Subject: [PATCH 06/59] ci: Add additional CI tasks that weren't previously required as dependencies of bedrock-go-tests --- .circleci/config.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index c193ef5d0..ac276f07d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1224,7 +1224,11 @@ workflows: target: test-external-geth - bedrock-go-tests: requires: + - go-mod-tidy + - cannon-build-test-vectors - cannon-go-lint-and-test + - check-generated-mocks-op-node + - check-generated-mocks-op-service - op-batcher-lint - op-bootnode-lint - op-bindings-lint @@ -1238,6 +1242,7 @@ workflows: - op-batcher-tests - op-bindings-tests - op-chain-ops-tests + - op-heartbeat-tests - op-node-tests - op-proposer-tests - op-challenger-tests @@ -1245,6 +1250,7 @@ workflows: - op-service-tests - op-e2e-WS-tests - op-e2e-HTTP-tests + - op-e2e-ext-geth-tests - docker-build: name: op-node-docker-build docker_file: op-node/Dockerfile From ac1a0e62fe7085c92584fa7960e9e0b5808c015f Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Fri, 1 Sep 2023 13:17:55 +1000 Subject: [PATCH 07/59] ci: Remove space from 'op-heartbeat tests' --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ac276f07d..174166550 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1142,7 +1142,7 @@ workflows: working_directory: proxyd - indexer-tests - go-lint-test-build: - name: op-heartbeat tests + name: op-heartbeat-tests binary_name: op-heartbeat working_directory: op-heartbeat - semgrep-scan From 08af0b59b106be4a68ea7d4eb33054abfec07350 Mon Sep 17 00:00:00 2001 From: Sabnock01 <24715302+Sabnock01@users.noreply.github.com> Date: Sun, 3 Sep 2023 02:32:06 -0500 Subject: [PATCH 08/59] docs: challenger typo --- specs/challenger.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/challenger.md b/specs/challenger.md index 85ca83322..4ffc2543f 100644 --- a/specs/challenger.md +++ b/specs/challenger.md @@ -73,7 +73,7 @@ to each of the different game types. For specification of dispute game types, se created by the `DisputeGameFactory` is equal to the output root of their `rollup-node` at the game's `l2BlockNumber`. - If it is, the Challenger should sign the [EIP-712 typeHash](./dispute-game.md) of the struct containing the `AttestationDisputeGame`'s `rootClaim` and `l2BlockNumber`. The Challenger should then submit the abi-encoded - signature to the `AttetationDisputeGame`'s `challenge` function. + signature to the `AttestationDisputeGame`'s `challenge` function. - If it is not, the Challenger should do nothing in support of this dispute game. ![Attestation `DisputeGameCreated` Diagram](./assets/challenger_attestation_dispute_game_created.png) From a40781fded2d8fb6807bea4dd86296a63688c49d Mon Sep 17 00:00:00 2001 From: Sabnock01 <24715302+Sabnock01@users.noreply.github.com> Date: Sun, 3 Sep 2023 02:40:08 -0500 Subject: [PATCH 09/59] docs: add op-preimage to directory structure --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index dab53b675..979793962 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ Refer to the Directory Structure section below to understand which packages are ├── op-exporter: Prometheus exporter client ├── op-heartbeat: Heartbeat monitor service ├── op-node: rollup consensus-layer client +├── op-preimage: Go bindings for Preimage Oracle ├── op-program: Fault proof program ├── op-proposer: L2-Output Submitter, submits proposals to L1 ├── op-service: Common codebase utilities From fab80efe419def3b8e9a9c6c2dd1868f72e19df5 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Mon, 4 Sep 2023 09:10:58 +1000 Subject: [PATCH 10/59] op-challenger: Fix error in make alphabet --- op-challenger/scripts/alphabet/init_game.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op-challenger/scripts/alphabet/init_game.sh b/op-challenger/scripts/alphabet/init_game.sh index 574500a32..de504199b 100755 --- a/op-challenger/scripts/alphabet/init_game.sh +++ b/op-challenger/scripts/alphabet/init_game.sh @@ -18,7 +18,7 @@ DEVNET_SPONSOR="ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 DISPUTE_GAME_FACTORY=$(jq -r .DisputeGameFactoryProxy $MONOREPO_DIR/.devnet/addresses.json) echo "----------------------------------------------------------------" -echo " Dispute Game Factory at $DISPUTE_GAME_PROXY" +echo " Dispute Game Factory at $DISPUTE_GAME_FACTORY" echo "----------------------------------------------------------------" L2_OUTPUT_ORACLE_PROXY=$(jq -r .L2OutputOracleProxy $MONOREPO_DIR/.devnet/addresses.json) From c3d04d3bf63cb14d1be63ef0aa49c10eee0c8c5f Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Mon, 4 Sep 2023 09:54:19 +1000 Subject: [PATCH 11/59] op-program: Recreate preimage data dir if required --- op-program/host/kvstore/disk.go | 17 ++++++++++++++++- op-program/host/kvstore/disk_test.go | 17 ++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/op-program/host/kvstore/disk.go b/op-program/host/kvstore/disk.go index 8f2a5b493..0f6bd1906 100644 --- a/op-program/host/kvstore/disk.go +++ b/op-program/host/kvstore/disk.go @@ -37,7 +37,7 @@ func (d *DiskKV) pathKey(k common.Hash) string { func (d *DiskKV) Put(k common.Hash, v []byte) error { d.Lock() defer d.Unlock() - f, err := os.CreateTemp(d.path, k.String()+".txt.*") + f, err := openTempFile(d.path, k.String()+".txt.*") if err != nil { return fmt.Errorf("failed to open temp file for pre-image %s: %w", k, err) } @@ -57,6 +57,21 @@ func (d *DiskKV) Put(k common.Hash, v []byte) error { return nil } +func openTempFile(dir string, nameTemplate string) (*os.File, error) { + f, err := os.CreateTemp(dir, nameTemplate) + // Directory has been deleted out from underneath us. Recreate it. + if errors.Is(err, os.ErrNotExist) { + if mkdirErr := os.MkdirAll(dir, 0777); mkdirErr != nil { + return nil, errors.Join(fmt.Errorf("failed to create directory %v: %w", dir, mkdirErr), err) + } + f, err = os.CreateTemp(dir, nameTemplate) + } + if err != nil { + return nil, err + } + return f, nil +} + func (d *DiskKV) Get(k common.Hash) ([]byte, error) { d.RLock() defer d.RUnlock() diff --git a/op-program/host/kvstore/disk_test.go b/op-program/host/kvstore/disk_test.go index ce6a34b1b..1ea0eaa2d 100644 --- a/op-program/host/kvstore/disk_test.go +++ b/op-program/host/kvstore/disk_test.go @@ -1,9 +1,24 @@ package kvstore -import "testing" +import ( + "path/filepath" + "testing" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" +) func TestDiskKV(t *testing.T) { tmp := t.TempDir() // automatically removed by testing cleanup kv := NewDiskKV(tmp) kvTest(t, kv) } + +func TestCreateMissingDirectory(t *testing.T) { + tmp := t.TempDir() + dir := filepath.Join(tmp, "data") + kv := NewDiskKV(dir) + val := []byte{1, 2, 3, 4} + key := crypto.Keccak256Hash(val) + require.NoError(t, kv.Put(key, val)) +} From c33e8084fa662e01532821eb649356ba65176f17 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Mon, 4 Sep 2023 10:38:26 +1000 Subject: [PATCH 12/59] op-node: Default to no netrestrict instead of allow none When p2p.netrestrict was not set, the empty string was being used as the list of allowed nodes, thus preventing any peers from connecting. --- op-node/flags/p2p_flags.go | 1 - op-node/p2p/cli/load_config.go | 11 ++++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/op-node/flags/p2p_flags.go b/op-node/flags/p2p_flags.go index 461282292..8117437d8 100644 --- a/op-node/flags/p2p_flags.go +++ b/op-node/flags/p2p_flags.go @@ -156,7 +156,6 @@ var ( Name: "p2p.netrestrict", Usage: "Comma-separated list of CIDR masks. P2P will only try to connect on these networks", Required: false, - Value: "", EnvVars: p2pEnv("NETRESTRICT"), } HostMux = &cli.StringFlag{ diff --git a/op-node/p2p/cli/load_config.go b/op-node/p2p/cli/load_config.go index c1e0f282e..349f212fd 100644 --- a/op-node/p2p/cli/load_config.go +++ b/op-node/p2p/cli/load_config.go @@ -194,13 +194,14 @@ func loadDiscoveryOpts(conf *p2p.Config, ctx *cli.Context) error { conf.Bootnodes = p2p.DefaultBootnodes } - netRestrict, err := netutil.ParseNetlist(ctx.String(flags.NetRestrict.Name)) - if err != nil { - return fmt.Errorf("failed to parse net list: %w", err) + if ctx.IsSet(flags.NetRestrict.Name) { + netRestrict, err := netutil.ParseNetlist(ctx.String(flags.NetRestrict.Name)) + if err != nil { + return fmt.Errorf("failed to parse net list: %w", err) + } + conf.NetRestrict = netRestrict } - conf.NetRestrict = netRestrict - return nil } From ff17f6c1539ac218bc3a84693bf8a61fba070d41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 20:22:32 +0000 Subject: [PATCH 13/59] build(deps-dev): bump @babel/eslint-parser from 7.22.10 to 7.22.15 Bumps [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) from 7.22.10 to 7.22.15. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.22.15/eslint/babel-eslint-parser) --- updated-dependencies: - dependency-name: "@babel/eslint-parser" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pnpm-lock.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 854ca3650..a93b961cc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,7 +17,7 @@ importers: devDependencies: '@babel/eslint-parser': specifier: ^7.18.2 - version: 7.22.10(@babel/core@7.22.10)(eslint@8.47.0) + version: 7.22.15(@babel/core@7.22.10)(eslint@8.47.0) '@changesets/changelog-github': specifier: ^0.4.8 version: 0.4.8 @@ -662,8 +662,8 @@ packages: - supports-color dev: true - /@babel/eslint-parser@7.22.10(@babel/core@7.22.10)(eslint@8.47.0): - resolution: {integrity: sha512-0J8DNPRXQRLeR9rPaUMM3fA+RbixjnVLe/MRMYCkp3hzgsSuxCHQ8NN8xQG1wIHKJ4a1DTROTvFJdW+B5/eOsg==} + /@babel/eslint-parser@7.22.15(@babel/core@7.22.10)(eslint@8.47.0): + resolution: {integrity: sha512-yc8OOBIQk1EcRrpizuARSQS0TWAcOMpEJ1aafhNznaeYkeL+OhqnDObGFylB8ka8VFF/sZc+S4RzHyO+3LjQxg==} engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} peerDependencies: '@babel/core': ^7.11.0 From fa2a69a59ab7ebb211f511fd4584678d11172d83 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Tue, 5 Sep 2023 07:44:30 +1000 Subject: [PATCH 14/59] Dockerfiles: Run go mod download with just the go.mod and go.sum files Avoids the need to re-run mod download when any source file changes and means most dockerfiles can reuse the cached layer with download already done. --- endpoint-monitor/Dockerfile | 11 +++++++---- indexer/Dockerfile | 11 +++++++---- op-batcher/Dockerfile | 11 +++++++---- op-challenger/Dockerfile | 11 +++++++---- op-node/Dockerfile | 11 +++++++---- op-program/Dockerfile | 11 +++++++---- op-proposer/Dockerfile | 11 +++++++---- 7 files changed, 49 insertions(+), 28 deletions(-) diff --git a/endpoint-monitor/Dockerfile b/endpoint-monitor/Dockerfile index 29649859a..ff4bf7ed2 100644 --- a/endpoint-monitor/Dockerfile +++ b/endpoint-monitor/Dockerfile @@ -2,18 +2,21 @@ FROM golang:1.20.7-alpine3.18 as builder RUN apk --no-cache add make jq bash git alpine-sdk +COPY ./go.mod /app/go.mod +COPY ./go.sum /app/go.sum + +WORKDIR /app + +RUN go mod download + COPY ./endpoint-monitor /app/endpoint-monitor 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 /app/endpoint-monitor -RUN go mod download - RUN make build FROM alpine:3.18 diff --git a/indexer/Dockerfile b/indexer/Dockerfile index e506981aa..2380ae160 100644 --- a/indexer/Dockerfile +++ b/indexer/Dockerfile @@ -2,18 +2,21 @@ FROM --platform=$BUILDPLATFORM golang:1.20.7-alpine3.18 as builder RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash +COPY ./go.mod /app/go.mod +COPY ./go.sum /app/go.sum + +WORKDIR /app + +RUN go mod download + # 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 WORKDIR /app/indexer -RUN go mod download - RUN make indexer FROM alpine:3.18 diff --git a/op-batcher/Dockerfile b/op-batcher/Dockerfile index c5212d054..7fd48a7c6 100644 --- a/op-batcher/Dockerfile +++ b/op-batcher/Dockerfile @@ -4,21 +4,24 @@ ARG VERSION=v0.0.0 RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash +COPY ./go.mod /app/go.mod +COPY ./go.sum /app/go.sum + +WORKDIR /app + +RUN go mod download + # build op-batcher with the shared go.mod & go.sum files COPY ./op-batcher /app/op-batcher COPY ./op-bindings /app/op-bindings COPY ./op-node /app/op-node COPY ./op-service /app/op-service COPY ./op-signer /app/op-signer -COPY ./go.mod /app/go.mod -COPY ./go.sum /app/go.sum COPY ./.git /app/.git WORKDIR /app/op-batcher -RUN go mod download - ARG TARGETOS TARGETARCH RUN make op-batcher VERSION="$VERSION" GOOS=$TARGETOS GOARCH=$TARGETARCH diff --git a/op-challenger/Dockerfile b/op-challenger/Dockerfile index da3083aa6..ae8c7dd12 100644 --- a/op-challenger/Dockerfile +++ b/op-challenger/Dockerfile @@ -4,6 +4,13 @@ ARG VERSION=v0.0.0 RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash +COPY ./go.mod /app/go.mod +COPY ./go.sum /app/go.sum + +WORKDIR /app + +RUN go mod download + # build op-challenger with the shared go.mod & go.sum files COPY ./op-challenger /app/op-challenger COPY ./op-program /app/op-program @@ -12,8 +19,6 @@ COPY ./op-bindings /app/op-bindings COPY ./op-node /app/op-node COPY ./op-service /app/op-service COPY ./op-signer /app/op-signer -COPY ./go.mod /app/go.mod -COPY ./go.sum /app/go.sum COPY ./.git /app/.git # Copy cannon and its dependencies @@ -23,8 +28,6 @@ COPY ./op-chain-ops /app/op-chain-ops WORKDIR /app/op-program -RUN go mod download - ARG TARGETOS TARGETARCH RUN make op-program-host VERSION="$VERSION" GOOS=$TARGETOS GOARCH=$TARGETARCH diff --git a/op-node/Dockerfile b/op-node/Dockerfile index b5abdae8c..f1a9f81b2 100644 --- a/op-node/Dockerfile +++ b/op-node/Dockerfile @@ -4,19 +4,22 @@ ARG VERSION=v0.0.0 RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash +COPY ./go.mod /app/go.mod +COPY ./go.sum /app/go.sum + +WORKDIR /app + +RUN go mod download + # build op-node with the shared go.mod & go.sum files COPY ./op-node /app/op-node COPY ./op-chain-ops /app/op-chain-ops COPY ./op-service /app/op-service COPY ./op-bindings /app/op-bindings -COPY ./go.mod /app/go.mod -COPY ./go.sum /app/go.sum COPY ./.git /app/.git WORKDIR /app/op-node -RUN go mod download - ARG TARGETOS TARGETARCH RUN make op-node VERSION="$VERSION" GOOS=$TARGETOS GOARCH=$TARGETARCH diff --git a/op-program/Dockerfile b/op-program/Dockerfile index e6a3b10ee..f25c9e87d 100644 --- a/op-program/Dockerfile +++ b/op-program/Dockerfile @@ -4,6 +4,13 @@ ARG VERSION=v0.0.0 RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash +COPY ./go.mod /app/go.mod +COPY ./go.sum /app/go.sum + +WORKDIR /app + +RUN go mod download + # build op-program with the shared go.mod & go.sum files COPY ./op-program /app/op-program COPY ./op-preimage /app/op-preimage @@ -11,14 +18,10 @@ COPY ./op-node /app/op-node COPY ./op-chain-ops /app/op-chain-ops COPY ./op-service /app/op-service COPY ./op-bindings /app/op-bindings -COPY ./go.mod /app/go.mod -COPY ./go.sum /app/go.sum COPY ./.git /app/.git WORKDIR /app/op-program -RUN go mod download - ARG TARGETOS TARGETARCH RUN make op-program VERSION="$VERSION" GOOS=$TARGETOS GOARCH=$TARGETARCH diff --git a/op-proposer/Dockerfile b/op-proposer/Dockerfile index 1db70c9c7..d41fcfcb2 100644 --- a/op-proposer/Dockerfile +++ b/op-proposer/Dockerfile @@ -4,20 +4,23 @@ ARG VERSION=v0.0.0 RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash +COPY ./go.mod /app/go.mod +COPY ./go.sum /app/go.sum + +WORKDIR /app + +RUN go mod download + # build op-proposer with the shared go.mod & go.sum files COPY ./op-proposer /app/op-proposer COPY ./op-bindings /app/op-bindings COPY ./op-node /app/op-node COPY ./op-service /app/op-service COPY ./op-signer /app/op-signer -COPY ./go.mod /app/go.mod -COPY ./go.sum /app/go.sum COPY ./.git /app/.git WORKDIR /app/op-proposer -RUN go mod download - ARG TARGETOS TARGETARCH RUN make op-proposer VERSION="$VERSION" GOOS=$TARGETOS GOARCH=$TARGETARCH From 524e7e2e098af2627e4ee269bb0afc5fa4a14aa8 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Tue, 5 Sep 2023 10:10:15 +1000 Subject: [PATCH 15/59] op-e2e: Add test that deploys a contract using a deposit tx --- op-e2e/deposit_test.go | 138 +++++++++++++++++++++++++++++++++++++++++ op-e2e/setup.go | 2 +- op-e2e/system_test.go | 62 ------------------ op-e2e/tx_helper.go | 12 ++-- 4 files changed, 146 insertions(+), 68 deletions(-) create mode 100644 op-e2e/deposit_test.go diff --git a/op-e2e/deposit_test.go b/op-e2e/deposit_test.go new file mode 100644 index 000000000..6a6ee774b --- /dev/null +++ b/op-e2e/deposit_test.go @@ -0,0 +1,138 @@ +package op_e2e + +import ( + "context" + "math/big" + "testing" + "time" + + "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/core/vm" + "github.com/stretchr/testify/require" +) + +func TestMintOnRevertedDeposit(t *testing.T) { + InitParallel(t) + cfg := DefaultSystemConfig(t) + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + defer sys.Close() + + l1Client := sys.Clients["l1"] + l2Verif := sys.Clients["verifier"] + + // create signer + aliceKey := cfg.Secrets.Alice + opts, err := bind.NewKeyedTransactorWithChainID(aliceKey, cfg.L1ChainIDBig()) + require.Nil(t, err) + fromAddr := opts.From + + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + startBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil) + cancel() + require.Nil(t, err) + + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + startNonce, err := l2Verif.NonceAt(ctx, fromAddr, nil) + require.NoError(t, err) + cancel() + + toAddr := common.Address{0xff, 0xff} + mintAmount := big.NewInt(9_000_000) + opts.Value = mintAmount + SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *DepositTxOpts) { + l2Opts.ToAddr = toAddr + // trigger a revert by transferring more than we have available + l2Opts.Value = new(big.Int).Mul(common.Big2, startBalance) + l2Opts.ExpectedStatus = types.ReceiptStatusFailed + }) + + // Confirm balance + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + endBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil) + cancel() + require.Nil(t, err) + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + toAddrBalance, err := l2Verif.BalanceAt(ctx, toAddr, nil) + require.NoError(t, err) + cancel() + + diff := new(big.Int) + diff = diff.Sub(endBalance, startBalance) + require.Equal(t, mintAmount, diff, "Did not get expected balance change") + require.Equal(t, common.Big0.Int64(), toAddrBalance.Int64(), "The recipient account balance should be zero") + + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + endNonce, err := l2Verif.NonceAt(ctx, fromAddr, nil) + require.NoError(t, err) + cancel() + require.Equal(t, startNonce+1, endNonce, "Nonce of deposit sender should increment on L2, even if the deposit fails") +} + +func TestDepositTxCreateContract(t *testing.T) { + InitParallel(t) + cfg := DefaultSystemConfig(t) + delete(cfg.Nodes, "verifier") + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + defer sys.Close() + + l1Client := sys.Clients["l1"] + l2Client := sys.Clients["sequencer"] + + opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Alice, cfg.L1ChainIDBig()) + require.Nil(t, err) + + // Simple constructor that is prefixed to the actual contract code + // Results in the contract code being returned as the code for the new contract + deployPrefixSize := byte(16) + deployPrefix := []byte{ + // Copy input data after this prefix into memory starting at address 0x00 + // CODECOPY arg size + byte(vm.PUSH1), deployPrefixSize, + byte(vm.CODESIZE), + byte(vm.SUB), + // CODECOPY arg offset + byte(vm.PUSH1), deployPrefixSize, + // CODECOPY arg destOffset + byte(vm.PUSH1), 0x00, + byte(vm.CODECOPY), + + // Return code from memory + // RETURN arg size + byte(vm.PUSH1), deployPrefixSize, + byte(vm.CODESIZE), + byte(vm.SUB), + // RETURN arg offset + byte(vm.PUSH1), 0x00, + byte(vm.RETURN), + } + // Stores the first word from call data code to storage slot 0 + sstoreContract := []byte{ + // Load first word from call data + byte(vm.PUSH1), 0x00, + byte(vm.CALLDATALOAD), + + // Store it to slot 0 + byte(vm.PUSH1), 0x00, + byte(vm.SSTORE), + } + + deployData := append(deployPrefix, sstoreContract...) + + l2Receipt := SendDepositTx(t, cfg, l1Client, l2Client, opts, func(l2Opts *DepositTxOpts) { + l2Opts.Data = deployData + l2Opts.Value = common.Big0 + l2Opts.IsCreation = true + l2Opts.ToAddr = common.Address{} + l2Opts.GasLimit = 1_000_000 + }) + require.NotEqual(t, common.Address{}, l2Receipt.ContractAddress, "should not have zero address") + code, err := l2Client.CodeAt(context.Background(), l2Receipt.ContractAddress, nil) + require.NoError(t, err, "get deployed contract code") + require.Equal(t, sstoreContract, code, "should have deployed correct contract code") +} diff --git a/op-e2e/setup.go b/op-e2e/setup.go index 67af46ead..8a3752fc5 100644 --- a/op-e2e/setup.go +++ b/op-e2e/setup.go @@ -84,7 +84,7 @@ func DefaultSystemConfig(t *testing.T) SystemConfig { require.NoError(t, err) deployConfig := config.DeployConfig.Copy() deployConfig.L1GenesisBlockTimestamp = hexutil.Uint64(time.Now().Unix()) - require.NoError(t, deployConfig.Check()) + require.NoError(t, deployConfig.Check(), "Deploy config is invalid, do you need to run make devnet-allocs?") l1Deployments := config.L1Deployments.Copy() require.NoError(t, l1Deployments.Check()) diff --git a/op-e2e/system_test.go b/op-e2e/system_test.go index 9674df55a..ae4255254 100644 --- a/op-e2e/system_test.go +++ b/op-e2e/system_test.go @@ -11,7 +11,6 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" @@ -337,67 +336,6 @@ func TestFinalize(t *testing.T) { require.NotZerof(t, l2Finalized.NumberU64(), "must have finalized L2 block") } -func TestMintOnRevertedDeposit(t *testing.T) { - InitParallel(t) - cfg := DefaultSystemConfig(t) - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - defer sys.Close() - - l1Client := sys.Clients["l1"] - l2Verif := sys.Clients["verifier"] - - l1Node := sys.EthInstances["l1"].(*GethInstance).Node - - // create signer - ks := l1Node.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) - opts, err := bind.NewKeyStoreTransactorWithChainID(ks, ks.Accounts()[0], cfg.L1ChainIDBig()) - require.Nil(t, err) - fromAddr := opts.From - - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) - startBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil) - cancel() - require.Nil(t, err) - - ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) - startNonce, err := l2Verif.NonceAt(ctx, fromAddr, nil) - require.NoError(t, err) - cancel() - - toAddr := common.Address{0xff, 0xff} - mintAmount := big.NewInt(9_000_000) - opts.Value = mintAmount - SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *DepositTxOpts) { - l2Opts.ToAddr = toAddr - // trigger a revert by transferring more than we have available - l2Opts.Value = new(big.Int).Mul(common.Big2, startBalance) - l2Opts.ExpectedStatus = types.ReceiptStatusFailed - }) - - // Confirm balance - ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) - endBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil) - cancel() - require.Nil(t, err) - ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) - toAddrBalance, err := l2Verif.BalanceAt(ctx, toAddr, nil) - require.NoError(t, err) - cancel() - - diff := new(big.Int) - diff = diff.Sub(endBalance, startBalance) - require.Equal(t, mintAmount, diff, "Did not get expected balance change") - require.Equal(t, common.Big0.Int64(), toAddrBalance.Int64(), "The recipient account balance should be zero") - - ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) - endNonce, err := l2Verif.NonceAt(ctx, fromAddr, nil) - require.NoError(t, err) - cancel() - require.Equal(t, startNonce+1, endNonce, "Nonce of deposit sender should increment on L2, even if the deposit fails") -} - func TestMissingBatchE2E(t *testing.T) { InitParallel(t) // Note this test zeroes the balance of the batch-submitter to make the batches unable to go into L1. diff --git a/op-e2e/tx_helper.go b/op-e2e/tx_helper.go index 5b17afe88..0f1170a14 100644 --- a/op-e2e/tx_helper.go +++ b/op-e2e/tx_helper.go @@ -21,7 +21,8 @@ import ( // The L1 transaction, including sender, is configured by the l1Opts param. // The L2 transaction options can be configured by modifying the DepositTxOps value supplied to applyL2Opts // Will verify that the transaction is included with the expected status on L1 and L2 -func SendDepositTx(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, l2Client *ethclient.Client, l1Opts *bind.TransactOpts, applyL2Opts DepositTxOptsFn) { +// Returns the receipt of the L2 transaction +func SendDepositTx(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, l2Client *ethclient.Client, l1Opts *bind.TransactOpts, applyL2Opts DepositTxOptsFn) *types.Receipt { l2Opts := defaultDepositTxOpts(l1Opts) applyL2Opts(l2Opts) @@ -38,16 +39,17 @@ func SendDepositTx(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, l require.Nil(t, err, "with deposit tx") // Wait for transaction on L1 - receipt, err := waitForTransaction(tx.Hash(), l1Client, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + l1Receipt, err := waitForTransaction(tx.Hash(), l1Client, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for deposit tx on L1") // Wait for transaction to be included on L2 - reconstructedDep, err := derive.UnmarshalDepositLogEvent(receipt.Logs[0]) + reconstructedDep, err := derive.UnmarshalDepositLogEvent(l1Receipt.Logs[0]) require.NoError(t, err, "Could not reconstruct L2 Deposit") tx = types.NewTx(reconstructedDep) - receipt, err = waitForTransaction(tx.Hash(), l2Client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) + l2Receipt, err := waitForTransaction(tx.Hash(), l2Client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) require.NoError(t, err) - require.Equal(t, l2Opts.ExpectedStatus, receipt.Status, "l2 transaction status") + require.Equal(t, l2Opts.ExpectedStatus, l2Receipt.Status, "l2 transaction status") + return l2Receipt } type DepositTxOptsFn func(l2Opts *DepositTxOpts) From c3dd839f13793ba4e3ca339ba6c58447fa0ddd52 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Tue, 5 Sep 2023 11:24:07 +1000 Subject: [PATCH 16/59] op-e2e: Add test for L2 transaction gossip --- op-e2e/l2_gossip_test.go | 65 ++++++++++++++++++++++++++++++++++++++++ op-e2e/tx_helper.go | 6 ++-- 2 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 op-e2e/l2_gossip_test.go diff --git a/op-e2e/l2_gossip_test.go b/op-e2e/l2_gossip_test.go new file mode 100644 index 000000000..c806647c8 --- /dev/null +++ b/op-e2e/l2_gossip_test.go @@ -0,0 +1,65 @@ +package op_e2e + +import ( + "context" + "testing" + "time" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/p2p" + "github.com/stretchr/testify/require" +) + +func TestTxGossip(t *testing.T) { + InitParallel(t) + cfg := DefaultSystemConfig(t) + gethOpts := []GethOption{ + func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { + ethCfg.RollupDisableTxPoolGossip = false + nodeCfg.P2P = p2p.Config{ + NoDiscovery: true, + ListenAddr: "127.0.0.1:0", + MaxPeers: 10, + } + return nil + }, + } + cfg.GethOptions["sequencer"] = gethOpts + cfg.GethOptions["verifier"] = gethOpts + sys, err := cfg.Start(t) + require.NoError(t, err, "Start system") + + seqClient := sys.Clients["sequencer"] + verifClient := sys.Clients["verifier"] + var seqInfo p2p.NodeInfo + require.NoError(t, seqClient.Client().Call(&seqInfo, "admin_nodeInfo"), "get sequencer node info") + var verifInfo p2p.NodeInfo + require.NoError(t, verifClient.Client().Call(&verifInfo, "admin_nodeInfo"), "get verifier node info") + + var peerAdded bool + require.NoError(t, verifClient.Client().Call(&peerAdded, "admin_addPeer", seqInfo.Enode), "add peer to verifier") + require.True(t, peerAdded, "should have added peer to verifier successfully") + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + err = wait.For(ctx, time.Second, func() (bool, error) { + var peerCount hexutil.Uint64 + if err := verifClient.Client().Call(&peerCount, "net_peerCount"); err != nil { + return false, err + } + t.Logf("Peer count %v", uint64(peerCount)) + return peerCount >= hexutil.Uint64(1), nil + }) + require.NoError(t, err, "wait for a peer to be connected") + + // Send a transaction to the verifier and it should be gossiped to the sequencer and included in a block. + SendL2Tx(t, cfg, verifClient, cfg.Secrets.Alice, func(opts *TxOpts) { + opts.ToAddr = &common.Address{0xaa} + opts.Value = common.Big1 + opts.VerifyOnClients(seqClient, verifClient) + }) +} diff --git a/op-e2e/tx_helper.go b/op-e2e/tx_helper.go index 5b17afe88..53e847560 100644 --- a/op-e2e/tx_helper.go +++ b/op-e2e/tx_helper.go @@ -91,16 +91,16 @@ func SendL2Tx(t *testing.T, cfg SystemConfig, l2Client *ethclient.Client, privKe ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() err := l2Client.SendTransaction(ctx, tx) - require.Nil(t, err, "Sending L2 tx") + require.NoError(t, err, "Sending L2 tx") receipt, err := waitForTransaction(tx.Hash(), l2Client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) - require.Nil(t, err, "Waiting for L2 tx") + require.NoError(t, err, "Waiting for L2 tx") require.Equal(t, opts.ExpectedStatus, receipt.Status, "TX should have expected status") for i, client := range opts.VerifyClients { t.Logf("Waiting for tx %v on verification client %d", tx.Hash(), i) receiptVerif, err := waitForTransaction(tx.Hash(), client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) - require.Nilf(t, err, "Waiting for L2 tx on verification client %d", i) + require.NoErrorf(t, err, "Waiting for L2 tx on verification client %d", i) require.Equalf(t, receipt, receiptVerif, "Receipts should be the same on sequencer and verification client %d", i) } return receipt From 96ac4c233404bb2178dc7df1a47fca2a6d5fbeb9 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Tue, 5 Sep 2023 11:30:31 +1000 Subject: [PATCH 17/59] op-e2e: Extract out helper methods for connecting peers. --- op-e2e/e2eutils/geth/peers.go | 49 +++++++++++++++++++++++++++++++++++ op-e2e/l2_gossip_test.go | 39 +++------------------------- 2 files changed, 52 insertions(+), 36 deletions(-) create mode 100644 op-e2e/e2eutils/geth/peers.go diff --git a/op-e2e/e2eutils/geth/peers.go b/op-e2e/e2eutils/geth/peers.go new file mode 100644 index 000000000..99f7ec5fe --- /dev/null +++ b/op-e2e/e2eutils/geth/peers.go @@ -0,0 +1,49 @@ +package geth + +import ( + "context" + "testing" + "time" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/p2p" + "github.com/stretchr/testify/require" +) + +// ConnectP2P creates a p2p peer connection between node1 and node2. +func ConnectP2P(t *testing.T, node1 *ethclient.Client, node2 *ethclient.Client) { + var targetInfo p2p.NodeInfo + require.NoError(t, node2.Client().Call(&targetInfo, "admin_nodeInfo"), "get node info") + + var peerAdded bool + require.NoError(t, node1.Client().Call(&peerAdded, "admin_addPeer", targetInfo.Enode), "add peer") + require.True(t, peerAdded, "should have added peer successfully") + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + err := wait.For(ctx, time.Second, func() (bool, error) { + var peerCount hexutil.Uint64 + if err := node1.Client().Call(&peerCount, "net_peerCount"); err != nil { + return false, err + } + t.Logf("Peer count %v", uint64(peerCount)) + return peerCount >= hexutil.Uint64(1), nil + }) + require.NoError(t, err, "wait for a peer to be connected") +} + +func WithP2P() func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { + return func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { + ethCfg.RollupDisableTxPoolGossip = false + nodeCfg.P2P = p2p.Config{ + NoDiscovery: true, + ListenAddr: "127.0.0.1:0", + MaxPeers: 10, + } + return nil + } +} diff --git a/op-e2e/l2_gossip_test.go b/op-e2e/l2_gossip_test.go index c806647c8..ff7f403e1 100644 --- a/op-e2e/l2_gossip_test.go +++ b/op-e2e/l2_gossip_test.go @@ -1,16 +1,10 @@ package op_e2e import ( - "context" "testing" - "time" - "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" "github.com/stretchr/testify/require" ) @@ -18,15 +12,7 @@ func TestTxGossip(t *testing.T) { InitParallel(t) cfg := DefaultSystemConfig(t) gethOpts := []GethOption{ - func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { - ethCfg.RollupDisableTxPoolGossip = false - nodeCfg.P2P = p2p.Config{ - NoDiscovery: true, - ListenAddr: "127.0.0.1:0", - MaxPeers: 10, - } - return nil - }, + geth.WithP2P(), } cfg.GethOptions["sequencer"] = gethOpts cfg.GethOptions["verifier"] = gethOpts @@ -35,26 +21,7 @@ func TestTxGossip(t *testing.T) { seqClient := sys.Clients["sequencer"] verifClient := sys.Clients["verifier"] - var seqInfo p2p.NodeInfo - require.NoError(t, seqClient.Client().Call(&seqInfo, "admin_nodeInfo"), "get sequencer node info") - var verifInfo p2p.NodeInfo - require.NoError(t, verifClient.Client().Call(&verifInfo, "admin_nodeInfo"), "get verifier node info") - - var peerAdded bool - require.NoError(t, verifClient.Client().Call(&peerAdded, "admin_addPeer", seqInfo.Enode), "add peer to verifier") - require.True(t, peerAdded, "should have added peer to verifier successfully") - - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - err = wait.For(ctx, time.Second, func() (bool, error) { - var peerCount hexutil.Uint64 - if err := verifClient.Client().Call(&peerCount, "net_peerCount"); err != nil { - return false, err - } - t.Logf("Peer count %v", uint64(peerCount)) - return peerCount >= hexutil.Uint64(1), nil - }) - require.NoError(t, err, "wait for a peer to be connected") + geth.ConnectP2P(t, seqClient, verifClient) // Send a transaction to the verifier and it should be gossiped to the sequencer and included in a block. SendL2Tx(t, cfg, verifClient, cfg.Secrets.Alice, func(opts *TxOpts) { From 4593a877d83b26b362f2c6f175938af254d8e38d Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Tue, 5 Sep 2023 12:54:39 +1000 Subject: [PATCH 18/59] op-e2e: Skip tests that specify GethOptions when using external clients --- op-e2e/setup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op-e2e/setup.go b/op-e2e/setup.go index 67af46ead..a191622d1 100644 --- a/op-e2e/setup.go +++ b/op-e2e/setup.go @@ -457,7 +457,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste ethClient = gethInst } else { if len(cfg.GethOptions[name]) > 0 { - t.Errorf("External L2 nodes do not support configuration through GethOptions") + t.Skip("External L2 nodes do not support configuration through GethOptions") } ethClient = (&ExternalRunner{ Name: name, From 271008bfcab972c057b1b85b5da3563f92df9c55 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Tue, 5 Sep 2023 13:16:49 +1000 Subject: [PATCH 19/59] codecov: Disable posting comment on PRs (#7106) --- codecov.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/codecov.yml b/codecov.yml index af5577570..3f84b2f3b 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,7 +1,4 @@ -comment: - layout: "reach, diff, flags, files" - behavior: default - require_changes: true # only post the comment if coverage changes +comment: false ignore: - "op-e2e" - "**/*.t.sol" From dbc719bd42b818b34947c612d484a7db484dadf5 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 19 Jul 2023 19:45:30 -0600 Subject: [PATCH 20/59] specs: span-batch spec fixes, issues found by @testinprod-io @ImTei Co-authored-by: Tei Im --- specs/span-batches.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/specs/span-batches.md b/specs/span-batches.md index 1a006ac59..1a01cb76c 100644 --- a/specs/span-batches.md +++ b/specs/span-batches.md @@ -64,7 +64,8 @@ Introduce version `1` to the [batch-format](./derivation.md#batch-format) table: Notation: `++`: concatenation of byte-strings. -`anchor`: first L2 block in the span +`span_start`: first L2 block in the span +`span_end`: last L2 block in the span `uvarint`: unsigned Base128 varint, as defined in [protobuf spec] [protobuf spec]: https://protobuf.dev/programming-guides/encoding/#varints @@ -72,11 +73,11 @@ Notation: Where: - `prefix = rel_timestamp ++ parent_check ++ l1_origin_check` - - `rel_timestamp`: relative time since genesis, i.e. `anchor.timestamp - config.genesis.timestamp`. - - `parent_check`: first 20 bytes of parent hash, i.e. `anchor.parent_hash[:20]`. + - `rel_timestamp`: relative time since genesis, i.e. `span_start.timestamp - config.genesis.timestamp`. + - `parent_check`: first 20 bytes of parent hash, i.e. `span_start.parent_hash[:20]`. - `l1_origin_check`: to ensure the intended L1 origins of this span of L2 blocks are consistent with the L1 chain, the blockhash of the last L1 origin is referenced. - The hash is truncated to 20 bytes for efficiency, i.e. `anchor.l1_origin.hash[:20]`. + The hash is truncated to 20 bytes for efficiency, i.e. `span_end.l1_origin.hash[:20]`. - `payload = block_count ++ block_tx_counts ++ tx_data_headers ++ tx_data ++ tx_sigs`: - `block_count`: `uvarint` number of L2 blocks. - `origin_bits`: bitlist of `block_count` bits, right-padded to a multiple of 8 bits: @@ -149,10 +150,10 @@ Span-batch rules, in validation order: - Rules: - `start_epoch_num + sequence_window_size < inclusion_block_number` -> `drop`: i.e. the batch must be included timely. - - `end_epoch_num < epoch.number` -> `future`: i.e. all referenced L1 epochs must be there. + - `start_epoch_num > epoch.number` -> `future`: i.e. all referenced L1 epochs must be there. - `end_epoch_num == epoch.number`: - If `batch.l1_origin_check != epoch.hash[:20]` -> `drop`: verify the batch is intended for this L1 chain. - - `end_epoch_num > epoch.number` -> `drop`: must have been duplicate batch, + - `end_epoch_num < epoch.number` -> `drop`: must have been duplicate batch, we may be past this L1 block in the safe L2 chain. - Max Sequencer time-drift checks: - Note: The max time-drift is enforced for the *batch as a whole*, to keep the possible output variants small. From 9b4b5c83fbd418053f39dbd592dc9591758ef7f9 Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 19 Jul 2023 20:06:54 -0600 Subject: [PATCH 21/59] specs: extended span-batches fixes: fix off-by-one to allow L1 origin progression, and do drop-check with start of span-batch to detect partially overlapping data --- specs/span-batches.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/specs/span-batches.md b/specs/span-batches.md index 1a01cb76c..e46599671 100644 --- a/specs/span-batches.md +++ b/specs/span-batches.md @@ -150,11 +150,12 @@ Span-batch rules, in validation order: - Rules: - `start_epoch_num + sequence_window_size < inclusion_block_number` -> `drop`: i.e. the batch must be included timely. - - `start_epoch_num > epoch.number` -> `future`: i.e. all referenced L1 epochs must be there. + - `start_epoch_num > epoch.number + 1` -> `future`: i.e. the L1 origin may jump to the next L1 block, but not further. - `end_epoch_num == epoch.number`: - If `batch.l1_origin_check != epoch.hash[:20]` -> `drop`: verify the batch is intended for this L1 chain. - - `end_epoch_num < epoch.number` -> `drop`: must have been duplicate batch, - we may be past this L1 block in the safe L2 chain. + - `start_epoch_num < epoch.number` -> `drop`: must have been duplicate batch, + we may be past this L1 block in the safe L2 chain. If a span-batch overlaps with older information, + it is dropped, since partially valid span-batches are not accepted. - Max Sequencer time-drift checks: - Note: The max time-drift is enforced for the *batch as a whole*, to keep the possible output variants small. - Variables: From f2bc0a79f788bd7eda91b119393e3c64641f81eb Mon Sep 17 00:00:00 2001 From: protolambda Date: Wed, 19 Jul 2023 20:21:07 -0600 Subject: [PATCH 22/59] specs: span-batches spec - fix lint and add explicit check of L1 origin of span-batch --- specs/span-batches.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/specs/span-batches.md b/specs/span-batches.md index e46599671..224a23e1d 100644 --- a/specs/span-batches.md +++ b/specs/span-batches.md @@ -150,9 +150,13 @@ Span-batch rules, in validation order: - Rules: - `start_epoch_num + sequence_window_size < inclusion_block_number` -> `drop`: i.e. the batch must be included timely. - - `start_epoch_num > epoch.number + 1` -> `future`: i.e. the L1 origin may jump to the next L1 block, but not further. - - `end_epoch_num == epoch.number`: - - If `batch.l1_origin_check != epoch.hash[:20]` -> `drop`: verify the batch is intended for this L1 chain. + - `start_epoch_num > epoch.number + 1` -> `future`: + i.e. the L1 origin may jump to the next L1 block, but not further. + - If `end_epoch_num >= inclusion_block_number` -> `drop`: + if the end of the span is past the L1 block it was included in, + it cannot possibly reference the chain it was included in, and is thus non-canonical. + - If `batch.l1_origin_check` does not match the canonical L1 chain at `end_epoch_num` -> `drop`: + verify the batch is intended for this L1 chain. - `start_epoch_num < epoch.number` -> `drop`: must have been duplicate batch, we may be past this L1 block in the safe L2 chain. If a span-batch overlaps with older information, it is dropped, since partially valid span-batches are not accepted. From 70de8ae199af254b7559b35adcef5fae31ef0968 Mon Sep 17 00:00:00 2001 From: Tei Im Date: Tue, 5 Sep 2023 15:23:14 +0200 Subject: [PATCH 23/59] specs: update span-batch format and rules - Update span-batch format - Fix batch derivation-rules - Add optimization-stategies section --- specs/span-batches.md | 211 ++++++++++++++++++++++++++++++++---------- 1 file changed, 164 insertions(+), 47 deletions(-) diff --git a/specs/span-batches.md b/specs/span-batches.md index 224a23e1d..9b1b17db5 100644 --- a/specs/span-batches.md +++ b/specs/span-batches.md @@ -9,6 +9,16 @@ - [Introduction](#introduction) - [Span batch format](#span-batch-format) +- [Optimization Strategies](#optimization-strategies) + - [Truncating information and storing only necessary data](#truncating-information-and-storing-only-necessary-data) + - [`tx_data_headers` removal from initial specs](#tx_data_headers-removal-from-initial-specs) + - [`Chain ID` removal from initial specs](#chain-id-removal-from-initial-specs) + - [Reorganization of constant length transaction fields](#reorganization-of-constant-length-transaction-fields) + - [RLP encoding for only variable length fields](#rlp-encoding-for-only-variable-length-fields) + - [Store `y_parity` instead of `v`](#store-y_parity-instead-of-v) + - [Adjust `txs` Data Layout for Better Compression](#adjust-txs-data-layout-for-better-compression) + - [`fee_recipients` Encoding Scheme](#fee_recipients-encoding-scheme) +- [How derivation works with Span Batch?](#how-derivation-works-with-span-batch) - [Integration](#integration) - [Channel Reader (Batch Decoding)](#channel-reader-batch-decoding) - [Batch Queue](#batch-queue) @@ -53,7 +63,7 @@ Span-batches address these inefficiencies, with a new batch format version. ## Span batch format -Note that span-batches, unlike previous V0 batches, +Note that span-batches, unlike previous singular batches, encode *a range of consecutive* L2 blocks at the same time. Introduce version `1` to the [batch-format](./derivation.md#batch-format) table: @@ -63,37 +73,69 @@ Introduce version `1` to the [batch-format](./derivation.md#batch-format) table: | 1 | `prefix ++ payload` | Notation: -`++`: concatenation of byte-strings. -`span_start`: first L2 block in the span -`span_end`: last L2 block in the span -`uvarint`: unsigned Base128 varint, as defined in [protobuf spec] + +- `++`: concatenation of byte-strings +- `span_start`: first L2 block in the span +- `span_end`: last L2 block in the span +- `uvarint`: unsigned Base128 varint, as defined in [protobuf spec] +- `rlp_encode`: a function that encodes a batch according to the [RLP format], + and `[x, y, z]` denotes a list containing items `x`, `y` and `z` [protobuf spec]: https://protobuf.dev/programming-guides/encoding/#varints Where: -- `prefix = rel_timestamp ++ parent_check ++ l1_origin_check` - - `rel_timestamp`: relative time since genesis, i.e. `span_start.timestamp - config.genesis.timestamp`. - - `parent_check`: first 20 bytes of parent hash, i.e. `span_start.parent_hash[:20]`. - - `l1_origin_check`: to ensure the intended L1 origins of this span of - L2 blocks are consistent with the L1 chain, the blockhash of the last L1 origin is referenced. - The hash is truncated to 20 bytes for efficiency, i.e. `span_end.l1_origin.hash[:20]`. -- `payload = block_count ++ block_tx_counts ++ tx_data_headers ++ tx_data ++ tx_sigs`: +- `prefix = rel_timestamp ++ l1_origin_num ++ parent_check ++ l1_origin_check` + - `rel_timestamp`: `uvarint` relative timestamp since L2 genesis, + i.e. `span_start.timestamp - config.genesis.timestamp`. + - `l1_origin_num`: `uvarint` number of last l1 origin number. i.e. `span_end.l1_origin.number` + - `parent_check`: first 20 bytes of parent hash, the hash is truncated to 20 bytes for efficiency, + i.e. `span_start.parent_hash[:20]`. + - `l1_origin_check`: the block hash of the last L1 origin is referenced. + The hash is truncated to 20 bytes for efficiency, i.e. `span_end.l1_origin.hash[:20]`. +- `payload = block_count ++ origin_bits ++ block_tx_counts ++ txs`: - `block_count`: `uvarint` number of L2 blocks. - `origin_bits`: bitlist of `block_count` bits, right-padded to a multiple of 8 bits: 1 bit per L2 block, indicating if the L1 origin changed this L2 block. - `block_tx_counts`: for each block, a `uvarint` of `len(block.transactions)`. - - `tx_data_headers`: lengths of each `tx_data` entry, encodes as concatenated `uvarint` entries, (empty if there are - no entries). - - `tx_data`: [EIP-2718] encoded transactions. - - The `tx_signature` is truncated from each [EIP-2718] encoded tx. To be reconstructed from `tx_sigs`. - - `legacy`: starting at `v` RLP field - - `1` ([EIP-2930]): starting at `signatureYParity` RLP field - - `2` ([EIP-1559]): starting at `signature_y_parity` RLP field - - `tx_sigs`: concatenated list of transaction signatures: - - `v`, or `y_parity`, is encoded as `uvarint` (some legacy transactions combine the chain ID) + - `txs`: L2 transactions which is reorganized and encoded as below. +- `txs = contract_creation_bits ++ y_parity_bits ++ tx_sigs ++ tx_tos ++ tx_datas ++ tx_nonces ++ tx_gases` + - `contract_creation_bits`: bit list of `sum(block_tx_counts)` bits, right-padded to a multiple of 8 bits, + 1 bit per L2 transactions, indicating if transaction is a contract creation transaction. + - `y_parity_bits`: bit list of `sum(block_tx_counts)` bits, right-padded to a multiple of 8 bits, + 1 bit per L2 transactions, indicating the y parity value when recovering transaction sender address. + - `tx_sigs`: concatenated list of transaction signatures - `r` is encoded as big-endian `uint256` - `s` is encoded as big-endian `uint256` + - `tx_tos`: concatenated list of `to` field. `to` field in contract creation transaction will be `nil` and ignored. + - `tx_datas`: concatenated list of variable length rlp encoded data, + matching the encoding of the fields as in the [EIP-2718] format of the `TransactionType`. + - `legacy`: `rlp_encode(value, gasPrice, data)` + - `1`: ([EIP-2930]): `0x01 ++ rlp_encode(value, gasPrice, data, accessList)` + - `2`: ([EIP-1559]): `0x02 ++ rlp_encode(value, max_priority_fee_per_gas, max_fee_per_gas, data, access_list)` + - `tx_nonces`: concatenated list of `uvarint` of `nonce` field. + - `tx_gases`: concatenated list of `uvarint` of gas limits. + - `legacy`: `gasLimit` + - `1`: ([EIP-2930]): `gasLimit` + - `2`: ([EIP-1559]): `gas_limit` + +Introduce version `2` to the [batch-format](./derivation.md#batch-format) table: + +| `batch_version` | `content` | +|-----------------|---------------------| +| 2 | `prefix ++ payload` | + +Where: + +- `prefix = rel_timestamp ++ l1_origin_num ++ parent_check ++ l1_origin_check`: + - Identical to `batch_version` 1 +- `payload = block_count ++ origin_bits ++ block_tx_counts ++ txs ++ fee_recipients`: + - Every field definition identical to `batch_version` 1 except that `fee_recipients` is + added to support more decentralized sequencing. + - `fee_recipients = fee_recipients_idxs + fee_recipients_set` + - `fee_recipients_set`: concatenated list of unique L2 fee recipient address. + - `fee_recipients_idxs`: for each block, + `uvarint` number of index to decode fee recipients from `fee_recipients_set`. [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718 @@ -101,13 +143,91 @@ Where: [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 -> **TODO research/experimentation questions:** -> -> - `tx_data` entries may be split up completely and tx attributes could be grouped into individual arrays, similar to - signatures. - > This may add more complexity, but organize data for improved compression. -> - Backtesting: using this format, how are different types of chain history affected? Improved or not? And by what - margin? +## Optimization Strategies + +### Truncating information and storing only necessary data + +The following fields stores truncated data: + +- `rel_timestamp`: We can save two bytes by storing `rel_timestamp` instead of the full `span_start.timestamp`. +- `parent_check` and `l1_origin_check`: We can save twelve bytes by truncating twelve bytes from the full hash, + while having enough safety. + +### `tx_data_headers` removal from initial specs + +We do not need to store length per each `tx_datas` elements even if those are variable length, +because the elements itself is RLP encoded, containing their length in RLP prefix. + +### `Chain ID` removal from initial specs + +Every transaction has chain id. We do not need to include chain id in span batch because L2 already knows its chain id, +and use its own value for processing span batches while derivation. + +### Reorganization of constant length transaction fields + +`signature`, `nonce`, `gaslimit`, `to` field are constant size, so these were split up completely and +are grouped into individual arrays. +This adds more complexity, but organizes data for improved compression by grouping data with similar data pattern. + +### RLP encoding for only variable length fields + +Further size optimization can be done by packing variable length fields, such as `access_list`. +However, doing this will introduce much more code complexity, comparing to benefiting by size reduction. + +Our goal is to find the sweet spot on code complexity - span batch size tradeoff. +I decided that using RLP for all variable length fields will be the best option, +not risking codebase with gnarly custom encoding/decoding implementations. + +### Store `y_parity` instead of `v` + +For legacy type transactions, `v = 2 * ChainID + y_parity`. For other types of transactions, `v = y_parity`. +We may only store `y_parity`, which is single bit per L2 transaction. + +This optimization will benefit more when ratio between number of legacy type transactions over number of transactions +excluding deposit tx is higher. +Deposit transactions are excluded in batches and are never written at L1 so excluded while analyzing. + +### Adjust `txs` Data Layout for Better Compression + +There are (7 choose 2) * 5! = 2520 permutations of ordering fields of `txs`. +It is not 7! because `contract_creation_bits` must be first decoded in order to decode `tx_tos`. +We experimented to find out the best layout for compression. +It turned out placing random data together(`TxSigs`, `TxTos`, `TxDatas`), +then placing leftovers helped gzip to gain more size reduction. + +### `fee_recipients` Encoding Scheme + +Let `K` := number of unique fee recipients(cardinality) per span batch. Let `N` := number of L2 blocks. +If we naively encode each fee recipients by concatenating every fee recipients, it will need `20 * N` bytes. +If we manage `fee_recipients_idxs` and `fee_recipients_set`, It will need at most `max uvarint size * N = 8 * N`, +`20 * K` bytes each. If `20 * N > 8 * N + 20 * K` then maintaining an index of fee recipients is reduces the size. + +we thought sequencer rotation happens not much often, so assumed that `K` will be much lesser than `N`. +The assumption makes upper inequality to hold. Therefore, we decided to manage `fee_recipients_idxs` and +`fee_recipients_set` separately. This adds complexity but reduces data. + +## How derivation works with Span Batch? + +- Block Timestamp + - The first L2 block's block timestamp is `rel_timestamp + L2Genesis.Timestamp`. + - Then we can derive other blocks timestamp by adding L2 block time for each. +- L1 Origin Number + - The parent of the first L2 block's L1 origin number is `l1_origin_num - sum(origin_bits)` + - Then we can derive other blocks' L1 origin number with `origin_bits` + - `ith block's L1 origin number = (i-1)th block's L1 origin number + (origin_bits[i] ? 1 : 0)` +- L1 Origin Hash + - We only need the `l1_origin_check`, the truncated L1 origin hash of the last L2 block of Span Batch. + - If the last block references canonical L1 chain as its origin, + we can ensure the all other blocks' origins are consistent with the canonical L1 chain. +- Parent hash + - In V0 Batch spec, we need batch's parent hash to validate if batch's parent is consistent with current L2 safe head. + - But in the case of Span Batch, because it contains consecutive L2 blocks in the span, + we do not need to validate all blocks' parent hash except the first block. +- Transactions + - Deposit transactions can be derived from its L1 origin, identical with V0 batch. + - User transactions can be derived by following way: + - Recover `V` value of TX signature from `y_parity_bits` and L2 chainId, as described in optimization strategies. + - When parsing `tx_tos`, `contract_creation_bits` is used to determine if the TX has `to` value or not. ## Integration @@ -115,11 +235,7 @@ Where: The Channel Reader decodes the span-batch, as described in the [span-batch format](#span-batch-format). -A set of derived attributes is computed, cached with the decoded result: - -- `l2_blocks_count`: number of L2 blocks in the span-batch -- `start_timestamp`: `config.genesis.timestamp + batch.rel_timestamp` -- `epoch_end`: +A set of derived attributes is computed as described above. Then cached with the decoded result: ### Batch Queue @@ -145,18 +261,19 @@ Span-batch rules, in validation order: which makes the later L2 blocks invalid. - Variables: - `origin_changed_bit = origin_bits[0]`: `true` if the first L2 block changed its L1 origin, `false` otherwise. - - `start_epoch_num = safe_l2_head.origin.block_number + (origin_changed_bit ? 1 : 0)` - - `end_epoch_num = safe_l2_head.origin.block_number + sum(origin_bits)`: block number of last referenced L1 origin + - `start_epoch_num = batch.l1_origin_num - sum(origin_bits) + (origin_changed_bit ? 1 : 0)` + - `end_epoch_num = batch.l1_origin_num` - Rules: - `start_epoch_num + sequence_window_size < inclusion_block_number` -> `drop`: i.e. the batch must be included timely. - - `start_epoch_num > epoch.number + 1` -> `future`: - i.e. the L1 origin may jump to the next L1 block, but not further. - - If `end_epoch_num >= inclusion_block_number` -> `drop`: - if the end of the span is past the L1 block it was included in, - it cannot possibly reference the chain it was included in, and is thus non-canonical. + - `start_epoch_num > epoch.number + 1` -> `drop`: + i.e. the L1 origin cannot change by more than one L1 block per L2 block. - If `batch.l1_origin_check` does not match the canonical L1 chain at `end_epoch_num` -> `drop`: verify the batch is intended for this L1 chain. + - After upper `l1_origin_check` check is passed, we don't need to check if the origin + is past `inclusion_block_number` because of the following invariant. + - Invariant: the epoch-num in the batch is always less than the inclusion block number, + if and only if the L1 epoch hash is correct. - `start_epoch_num < epoch.number` -> `drop`: must have been duplicate batch, we may be past this L1 block in the safe L2 chain. If a span-batch overlaps with older information, it is dropped, since partially valid span-batches are not accepted. @@ -165,25 +282,25 @@ Span-batch rules, in validation order: - Variables: - `block_input`: an L2 block from the span-batch, with L1 origin as derived from the `origin_bits` and now established canonical L1 chain. - - `next_epoch` is relative to the `block_input`, - and may reach to the next origin outside of the L1 origins of the span. + - `next_epoch`: `block_input.origin`'s next L1 block. + It may reach to the next origin outside the L1 origins of the span. - Rules: - For each `block_input` that can be read from the span-batch: - `block_input.timestamp < block_input.origin.time` -> `drop`: enforce the min L2 timestamp rule. - `block_input.timestamp > block_input.origin.time + max_sequencer_drift`: enforce the L2 timestamp drift rule, but with exceptions to preserve above min L2 timestamp invariant: - `len(block_input.transactions) == 0`: - - `epoch.number == batch.epoch_num`: - this implies the batch does not already advance the L1 origin, + - `origin_bits[i] == 0`: `i` is the index of `block_input` in the span batch. + So this implies the block_input did not advance the L1 origin, and must thus be checked against `next_epoch`. - If `next_epoch` is not known -> `undecided`: without the next L1 origin we cannot yet determine if time invariant could have been kept. - - If `batch.timestamp >= next_epoch.time` -> `drop`: + - If `block_input.timestamp >= next_epoch.time` -> `drop`: the batch could have adopted the next L1 origin without breaking the `L2 time >= L1 time` invariant. - - `len(batch.transactions) > 0`: -> `drop`: + - `len(block_input.transactions) > 0`: -> `drop`: when exceeding the sequencer time drift, never allow the sequencer to include transactions. - And for all transactions: - - `drop` if the `batch.transactions` list contains a transaction + - `drop` if the `batch.tx_datas` list contains a transaction that is invalid or derived by other means exclusively: - any transaction that is empty (zero length `tx_data`) - any [deposited transactions][g-deposit-tx-type] (identified by the transaction type prefix byte in `tx_data`) From 07cf16db077506b1259952d4e6d9d2b4ec0b414d Mon Sep 17 00:00:00 2001 From: Andreas Bigger Date: Thu, 31 Aug 2023 15:46:04 -0400 Subject: [PATCH 24/59] Add Game Status Tracking GaugeVec --- op-challenger/game/fault/agent.go | 11 ++--- op-challenger/game/fault/agent_test.go | 27 +++++++------ op-challenger/game/fault/loader.go | 5 ++- op-challenger/game/fault/loader_test.go | 9 +++-- op-challenger/game/fault/player.go | 40 +++++++++---------- op-challenger/game/fault/player_test.go | 35 ++++++++-------- .../game/fault/responder/responder.go | 11 ++--- .../game/fault/responder/responder_test.go | 7 ++-- op-challenger/game/fault/types/types.go | 31 -------------- op-challenger/game/fault/types/types_test.go | 23 ----------- op-challenger/game/monitor.go | 4 -- op-challenger/game/monitor_test.go | 3 +- op-challenger/game/scheduler/coordinator.go | 31 +++++++++++--- .../game/scheduler/coordinator_test.go | 26 +++++++----- op-challenger/game/scheduler/scheduler.go | 8 +++- .../game/scheduler/scheduler_test.go | 5 ++- op-challenger/game/scheduler/types.go | 10 +++-- op-challenger/game/scheduler/worker.go | 2 +- op-challenger/game/scheduler/worker_test.go | 16 ++++---- op-challenger/game/service.go | 3 +- op-challenger/game/types/types.go | 35 ++++++++++++++++ op-challenger/game/types/types_test.go | 30 ++++++++++++++ op-challenger/metrics/metrics.go | 22 +++++++++- op-challenger/metrics/noop.go | 12 ++++-- 24 files changed, 240 insertions(+), 166 deletions(-) create mode 100644 op-challenger/game/types/types.go create mode 100644 op-challenger/game/types/types_test.go diff --git a/op-challenger/game/fault/agent.go b/op-challenger/game/fault/agent.go index 996901e23..5f12467e9 100644 --- a/op-challenger/game/fault/agent.go +++ b/op-challenger/game/fault/agent.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/fault/solver" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum/go-ethereum/log" ) @@ -14,7 +15,7 @@ import ( // Responder takes a response action & executes. // For full op-challenger this means executing the transaction on chain. type Responder interface { - CallResolve(ctx context.Context) (types.GameStatus, error) + CallResolve(ctx context.Context) (gameTypes.GameStatus, error) Resolve(ctx context.Context) error Respond(ctx context.Context, response types.Claim) error Step(ctx context.Context, stepData types.StepCallData) error @@ -74,10 +75,10 @@ func (a *Agent) Act(ctx context.Context) error { // shouldResolve returns true if the agent should resolve the game. // This method will return false if the game is still in progress. -func (a *Agent) shouldResolve(status types.GameStatus) bool { - expected := types.GameStatusDefenderWon +func (a *Agent) shouldResolve(status gameTypes.GameStatus) bool { + expected := gameTypes.GameStatusDefenderWon if a.agreeWithProposedOutput { - expected = types.GameStatusChallengerWon + expected = gameTypes.GameStatusChallengerWon } if expected != status { a.log.Warn("Game will be lost", "expected", expected, "actual", status) @@ -89,7 +90,7 @@ func (a *Agent) shouldResolve(status types.GameStatus) bool { // Returns true if the game is resolvable (regardless of whether it was actually resolved) func (a *Agent) tryResolve(ctx context.Context) bool { status, err := a.responder.CallResolve(ctx) - if err != nil || status == types.GameStatusInProgress { + if err != nil || status == gameTypes.GameStatusInProgress { return false } if !a.shouldResolve(status) { diff --git a/op-challenger/game/fault/agent_test.go b/op-challenger/game/fault/agent_test.go index a255249d0..3a7d764f8 100644 --- a/op-challenger/game/fault/agent_test.go +++ b/op-challenger/game/fault/agent_test.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/fault/test" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" @@ -19,16 +20,16 @@ import ( func TestShouldResolve(t *testing.T) { t.Run("AgreeWithProposedOutput", func(t *testing.T) { agent, _, _ := setupTestAgent(t, true) - require.False(t, agent.shouldResolve(types.GameStatusDefenderWon)) - require.True(t, agent.shouldResolve(types.GameStatusChallengerWon)) - require.False(t, agent.shouldResolve(types.GameStatusInProgress)) + require.False(t, agent.shouldResolve(gameTypes.GameStatusDefenderWon)) + require.True(t, agent.shouldResolve(gameTypes.GameStatusChallengerWon)) + require.False(t, agent.shouldResolve(gameTypes.GameStatusInProgress)) }) t.Run("DisagreeWithProposedOutput", func(t *testing.T) { agent, _, _ := setupTestAgent(t, false) - require.True(t, agent.shouldResolve(types.GameStatusDefenderWon)) - require.False(t, agent.shouldResolve(types.GameStatusChallengerWon)) - require.False(t, agent.shouldResolve(types.GameStatusInProgress)) + require.True(t, agent.shouldResolve(gameTypes.GameStatusDefenderWon)) + require.False(t, agent.shouldResolve(gameTypes.GameStatusChallengerWon)) + require.False(t, agent.shouldResolve(gameTypes.GameStatusInProgress)) }) } @@ -38,31 +39,31 @@ func TestDoNotMakeMovesWhenGameIsResolvable(t *testing.T) { tests := []struct { name string agreeWithProposedOutput bool - callResolveStatus types.GameStatus + callResolveStatus gameTypes.GameStatus shouldResolve bool }{ { name: "Agree_Losing", agreeWithProposedOutput: true, - callResolveStatus: types.GameStatusDefenderWon, + callResolveStatus: gameTypes.GameStatusDefenderWon, shouldResolve: false, }, { name: "Agree_Winning", agreeWithProposedOutput: true, - callResolveStatus: types.GameStatusChallengerWon, + callResolveStatus: gameTypes.GameStatusChallengerWon, shouldResolve: true, }, { name: "Disagree_Losing", agreeWithProposedOutput: false, - callResolveStatus: types.GameStatusChallengerWon, + callResolveStatus: gameTypes.GameStatusChallengerWon, shouldResolve: false, }, { name: "Disagree_Winning", agreeWithProposedOutput: false, - callResolveStatus: types.GameStatusDefenderWon, + callResolveStatus: gameTypes.GameStatusDefenderWon, shouldResolve: true, }, } @@ -126,14 +127,14 @@ func (s *stubClaimLoader) FetchClaims(ctx context.Context) ([]types.Claim, error type stubResponder struct { callResolveCount int - callResolveStatus types.GameStatus + callResolveStatus gameTypes.GameStatus callResolveErr error resolveCount int resolveErr error } -func (s *stubResponder) CallResolve(ctx context.Context) (types.GameStatus, error) { +func (s *stubResponder) CallResolve(ctx context.Context) (gameTypes.GameStatus, error) { s.callResolveCount++ return s.callResolveStatus, s.callResolveErr } diff --git a/op-challenger/game/fault/loader.go b/op-challenger/game/fault/loader.go index b0f68cc69..410d1b4ef 100644 --- a/op-challenger/game/fault/loader.go +++ b/op-challenger/game/fault/loader.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -49,9 +50,9 @@ func NewLoaderFromBindings(fdgAddr common.Address, client bind.ContractCaller) ( } // GetGameStatus returns the current game status. -func (l *loader) GetGameStatus(ctx context.Context) (types.GameStatus, error) { +func (l *loader) GetGameStatus(ctx context.Context) (gameTypes.GameStatus, error) { status, err := l.caller.Status(&bind.CallOpts{Context: ctx}) - return types.GameStatus(status), err + return gameTypes.GameStatus(status), err } // GetClaimCount returns the number of claims in the game. diff --git a/op-challenger/game/fault/loader_test.go b/op-challenger/game/fault/loader_test.go index fb1f8898f..d715adf6e 100644 --- a/op-challenger/game/fault/loader_test.go +++ b/op-challenger/game/fault/loader_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -30,15 +31,15 @@ func TestLoader_GetGameStatus(t *testing.T) { }{ { name: "challenger won status", - status: uint8(types.GameStatusChallengerWon), + status: uint8(gameTypes.GameStatusChallengerWon), }, { name: "defender won status", - status: uint8(types.GameStatusDefenderWon), + status: uint8(gameTypes.GameStatusDefenderWon), }, { name: "in progress status", - status: uint8(types.GameStatusInProgress), + status: uint8(gameTypes.GameStatusInProgress), }, { name: "error bubbled up", @@ -57,7 +58,7 @@ func TestLoader_GetGameStatus(t *testing.T) { require.ErrorIs(t, err, mockStatusError) } else { require.NoError(t, err) - require.Equal(t, types.GameStatus(test.status), status) + require.Equal(t, gameTypes.GameStatus(test.status), status) } }) } diff --git a/op-challenger/game/fault/player.go b/op-challenger/game/fault/player.go index 52e501ca5..8e1e68264 100644 --- a/op-challenger/game/fault/player.go +++ b/op-challenger/game/fault/player.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -22,7 +23,7 @@ import ( type actor func(ctx context.Context) error type GameInfo interface { - GetGameStatus(context.Context) (types.GameStatus, error) + GetGameStatus(context.Context) (gameTypes.GameStatus, error) GetClaimCount(context.Context) (uint64, error) } @@ -31,8 +32,7 @@ type GamePlayer struct { agreeWithProposedOutput bool loader GameInfo logger log.Logger - - completed bool + status gameTypes.GameStatus } func NewGamePlayer( @@ -57,14 +57,14 @@ func NewGamePlayer( if err != nil { return nil, fmt.Errorf("failed to fetch game status: %w", err) } - if status != types.GameStatusInProgress { + if status != gameTypes.GameStatusInProgress { logger.Info("Game already resolved", "status", status) // Game is already complete so skip creating the trace provider, loading game inputs etc. return &GamePlayer{ logger: logger, loader: loader, agreeWithProposedOutput: cfg.AgreeWithProposedOutput, - completed: true, + status: status, // Act function does nothing because the game is already complete act: func(ctx context.Context) error { return nil @@ -111,32 +111,32 @@ func NewGamePlayer( agreeWithProposedOutput: cfg.AgreeWithProposedOutput, loader: loader, logger: logger, - completed: status != types.GameStatusInProgress, + status: status, }, nil } -func (g *GamePlayer) ProgressGame(ctx context.Context) bool { - if g.completed { +func (g *GamePlayer) ProgressGame(ctx context.Context) gameTypes.GameStatus { + if g.status != gameTypes.GameStatusInProgress { // Game is already complete so don't try to perform further actions. g.logger.Trace("Skipping completed game") - return true + return g.status } g.logger.Trace("Checking if actions are required") if err := g.act(ctx); err != nil { g.logger.Error("Error when acting on game", "err", err) } - if status, err := g.loader.GetGameStatus(ctx); err != nil { + status, err := g.loader.GetGameStatus(ctx) + if err != nil { g.logger.Warn("Unable to retrieve game status", "err", err) - } else { - g.logGameStatus(ctx, status) - g.completed = status != types.GameStatusInProgress - return g.completed + return gameTypes.GameStatusInProgress } - return false + g.logGameStatus(ctx, status) + g.status = status + return status } -func (g *GamePlayer) logGameStatus(ctx context.Context, status types.GameStatus) { - if status == types.GameStatusInProgress { +func (g *GamePlayer) logGameStatus(ctx context.Context, status gameTypes.GameStatus) { + if status == gameTypes.GameStatusInProgress { claimCount, err := g.loader.GetClaimCount(ctx) if err != nil { g.logger.Error("Failed to get claim count for in progress game", "err", err) @@ -145,11 +145,11 @@ func (g *GamePlayer) logGameStatus(ctx context.Context, status types.GameStatus) g.logger.Info("Game info", "claims", claimCount, "status", status) return } - var expectedStatus types.GameStatus + var expectedStatus gameTypes.GameStatus if g.agreeWithProposedOutput { - expectedStatus = types.GameStatusChallengerWon + expectedStatus = gameTypes.GameStatusChallengerWon } else { - expectedStatus = types.GameStatusDefenderWon + expectedStatus = gameTypes.GameStatusDefenderWon } if expectedStatus == status { g.logger.Info("Game won", "status", status) diff --git a/op-challenger/game/fault/player_test.go b/op-challenger/game/fault/player_test.go index 9ec939021..8a9f5789c 100644 --- a/op-challenger/game/fault/player_test.go +++ b/op-challenger/game/fault/player_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -22,8 +23,8 @@ var ( func TestProgressGame_LogErrorFromAct(t *testing.T) { handler, game, actor := setupProgressGameTest(t, true) actor.actErr = errors.New("boom") - done := game.ProgressGame(context.Background()) - require.False(t, done, "should not be done") + status := game.ProgressGame(context.Background()) + require.Equal(t, gameTypes.GameStatusInProgress, status) require.Equal(t, 1, actor.callCount, "should perform next actions") errLog := handler.FindLog(log.LvlError, "Error when acting on game") require.NotNil(t, errLog, "should log error") @@ -38,42 +39,42 @@ func TestProgressGame_LogErrorFromAct(t *testing.T) { func TestProgressGame_LogGameStatus(t *testing.T) { tests := []struct { name string - status types.GameStatus + status gameTypes.GameStatus agreeWithOutput bool logLevel log.Lvl logMsg string }{ { name: "GameLostAsDefender", - status: types.GameStatusChallengerWon, + status: gameTypes.GameStatusChallengerWon, agreeWithOutput: false, logLevel: log.LvlError, logMsg: "Game lost", }, { name: "GameLostAsChallenger", - status: types.GameStatusDefenderWon, + status: gameTypes.GameStatusDefenderWon, agreeWithOutput: true, logLevel: log.LvlError, logMsg: "Game lost", }, { name: "GameWonAsDefender", - status: types.GameStatusDefenderWon, + status: gameTypes.GameStatusDefenderWon, agreeWithOutput: false, logLevel: log.LvlInfo, logMsg: "Game won", }, { name: "GameWonAsChallenger", - status: types.GameStatusChallengerWon, + status: gameTypes.GameStatusChallengerWon, agreeWithOutput: true, logLevel: log.LvlInfo, logMsg: "Game won", }, { name: "GameInProgress", - status: types.GameStatusInProgress, + status: gameTypes.GameStatusInProgress, agreeWithOutput: true, logLevel: log.LvlInfo, logMsg: "Game info", @@ -85,9 +86,9 @@ func TestProgressGame_LogGameStatus(t *testing.T) { handler, game, gameState := setupProgressGameTest(t, test.agreeWithOutput) gameState.status = test.status - done := game.ProgressGame(context.Background()) + status := game.ProgressGame(context.Background()) require.Equal(t, 1, gameState.callCount, "should perform next actions") - require.Equal(t, test.status != types.GameStatusInProgress, done, "should be done when not in progress") + require.Equal(t, test.status, status) errLog := handler.FindLog(test.logLevel, test.logMsg) require.NotNil(t, errLog, "should log game result") require.Equal(t, test.status, errLog.GetContextValue("status")) @@ -96,19 +97,19 @@ func TestProgressGame_LogGameStatus(t *testing.T) { } func TestDoNotActOnCompleteGame(t *testing.T) { - for _, status := range []types.GameStatus{types.GameStatusChallengerWon, types.GameStatusDefenderWon} { + for _, status := range []gameTypes.GameStatus{gameTypes.GameStatusChallengerWon, gameTypes.GameStatusDefenderWon} { t.Run(status.String(), func(t *testing.T) { _, game, gameState := setupProgressGameTest(t, true) gameState.status = status - done := game.ProgressGame(context.Background()) + fetched := game.ProgressGame(context.Background()) require.Equal(t, 1, gameState.callCount, "acts the first time") - require.True(t, done, "should be done") + require.Equal(t, status, fetched) // Should not act when it knows the game is already complete - done = game.ProgressGame(context.Background()) + fetched = game.ProgressGame(context.Background()) require.Equal(t, 1, gameState.callCount, "does not act after game is complete") - require.True(t, done, "should still be done") + require.Equal(t, status, fetched) }) } } @@ -166,7 +167,7 @@ func setupProgressGameTest(t *testing.T, agreeWithProposedRoot bool) (*testlog.C } type stubGameState struct { - status types.GameStatus + status gameTypes.GameStatus claimCount uint64 callCount int actErr error @@ -178,7 +179,7 @@ func (s *stubGameState) Act(ctx context.Context) error { return s.actErr } -func (s *stubGameState) GetGameStatus(ctx context.Context) (types.GameStatus, error) { +func (s *stubGameState) GetGameStatus(ctx context.Context) (gameTypes.GameStatus, error) { return s.status, nil } diff --git a/op-challenger/game/fault/responder/responder.go b/op-challenger/game/fault/responder/responder.go index 07c1c3771..69ff3db88 100644 --- a/op-challenger/game/fault/responder/responder.go +++ b/op-challenger/game/fault/responder/responder.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum" @@ -81,23 +82,23 @@ func (r *faultResponder) BuildTx(ctx context.Context, response types.Claim) ([]b // CallResolve determines if the resolve function on the fault dispute game contract // would succeed. Returns the game status if the call would succeed, errors otherwise. -func (r *faultResponder) CallResolve(ctx context.Context) (types.GameStatus, error) { +func (r *faultResponder) CallResolve(ctx context.Context) (gameTypes.GameStatus, error) { txData, err := r.buildResolveData() if err != nil { - return types.GameStatusInProgress, err + return gameTypes.GameStatusInProgress, err } res, err := r.txMgr.Call(ctx, ethereum.CallMsg{ To: &r.fdgAddr, Data: txData, }, nil) if err != nil { - return types.GameStatusInProgress, err + return gameTypes.GameStatusInProgress, err } var status uint8 if err = r.fdgAbi.UnpackIntoInterface(&status, "resolve", res); err != nil { - return types.GameStatusInProgress, err + return gameTypes.GameStatusInProgress, err } - return types.GameStatusFromUint8(status) + return gameTypes.GameStatusFromUint8(status) } // Resolve executes a resolve transaction to resolve a fault dispute game. diff --git a/op-challenger/game/fault/responder/responder_test.go b/op-challenger/game/fault/responder/responder_test.go index b098229ff..bb91f39e5 100644 --- a/op-challenger/game/fault/responder/responder_test.go +++ b/op-challenger/game/fault/responder/responder_test.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-service/txmgr" @@ -32,7 +33,7 @@ func TestCallResolve(t *testing.T) { mockTxMgr.callFails = true status, err := responder.CallResolve(context.Background()) require.ErrorIs(t, err, mockCallError) - require.Equal(t, types.GameStatusInProgress, status) + require.Equal(t, gameTypes.GameStatusInProgress, status) require.Equal(t, 0, mockTxMgr.calls) }) @@ -41,7 +42,7 @@ func TestCallResolve(t *testing.T) { mockTxMgr.callBytes = []byte{0x00, 0x01} status, err := responder.CallResolve(context.Background()) require.Error(t, err) - require.Equal(t, types.GameStatusInProgress, status) + require.Equal(t, gameTypes.GameStatusInProgress, status) require.Equal(t, 1, mockTxMgr.calls) }) @@ -49,7 +50,7 @@ func TestCallResolve(t *testing.T) { responder, mockTxMgr := newTestFaultResponder(t) status, err := responder.CallResolve(context.Background()) require.NoError(t, err) - require.Equal(t, types.GameStatusInProgress, status) + require.Equal(t, gameTypes.GameStatusInProgress, status) require.Equal(t, 1, mockTxMgr.calls) }) } diff --git a/op-challenger/game/fault/types/types.go b/op-challenger/game/fault/types/types.go index 92da98d82..9e2fc3983 100644 --- a/op-challenger/game/fault/types/types.go +++ b/op-challenger/game/fault/types/types.go @@ -3,7 +3,6 @@ package types import ( "context" "errors" - "fmt" "math/big" "github.com/ethereum/go-ethereum/common" @@ -13,36 +12,6 @@ var ( ErrGameDepthReached = errors.New("game depth reached") ) -type GameStatus uint8 - -const ( - GameStatusInProgress GameStatus = iota - GameStatusChallengerWon - GameStatusDefenderWon -) - -// String returns the string representation of the game status. -func (s GameStatus) String() string { - switch s { - case GameStatusInProgress: - return "In Progress" - case GameStatusChallengerWon: - return "Challenger Won" - case GameStatusDefenderWon: - return "Defender Won" - default: - return "Unknown" - } -} - -// GameStatusFromUint8 returns a game status from the uint8 representation. -func GameStatusFromUint8(i uint8) (GameStatus, error) { - if i > 2 { - return GameStatus(i), fmt.Errorf("invalid game status: %d", i) - } - return GameStatus(i), nil -} - // PreimageOracleData encapsulates the preimage oracle data // to load into the onchain oracle. type PreimageOracleData struct { diff --git a/op-challenger/game/fault/types/types_test.go b/op-challenger/game/fault/types/types_test.go index 737358ba6..699e3f614 100644 --- a/op-challenger/game/fault/types/types_test.go +++ b/op-challenger/game/fault/types/types_test.go @@ -1,34 +1,11 @@ package types import ( - "fmt" "testing" "github.com/stretchr/testify/require" ) -var validGameStatuses = []GameStatus{ - GameStatusInProgress, - GameStatusChallengerWon, - GameStatusDefenderWon, -} - -func TestGameStatusFromUint8(t *testing.T) { - for _, status := range validGameStatuses { - t.Run(fmt.Sprintf("Valid Game Status %v", status), func(t *testing.T) { - parsed, err := GameStatusFromUint8(uint8(status)) - require.NoError(t, err) - require.Equal(t, status, parsed) - }) - } - - t.Run("Invalid", func(t *testing.T) { - status, err := GameStatusFromUint8(3) - require.Error(t, err) - require.Equal(t, GameStatus(3), status) - }) -} - func TestNewPreimageOracleData(t *testing.T) { t.Run("LocalData", func(t *testing.T) { data := NewPreimageOracleData([]byte{1, 2, 3}, []byte{4, 5, 6}, 7) diff --git a/op-challenger/game/monitor.go b/op-challenger/game/monitor.go index 303b54608..6f205fab3 100644 --- a/op-challenger/game/monitor.go +++ b/op-challenger/game/monitor.go @@ -8,7 +8,6 @@ import ( "time" "github.com/ethereum-optimism/optimism/op-challenger/game/scheduler" - "github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-service/clock" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" @@ -27,7 +26,6 @@ type gameScheduler interface { type gameMonitor struct { logger log.Logger - metrics metrics.Metricer clock clock.Clock source gameSource scheduler gameScheduler @@ -38,7 +36,6 @@ type gameMonitor struct { func newGameMonitor( logger log.Logger, - m metrics.Metricer, cl clock.Clock, source gameSource, scheduler gameScheduler, @@ -48,7 +45,6 @@ func newGameMonitor( ) *gameMonitor { return &gameMonitor{ logger: logger, - metrics: m, clock: cl, scheduler: scheduler, source: source, diff --git a/op-challenger/game/monitor_test.go b/op-challenger/game/monitor_test.go index 105f8f733..732554c0b 100644 --- a/op-challenger/game/monitor_test.go +++ b/op-challenger/game/monitor_test.go @@ -6,7 +6,6 @@ import ( "testing" "time" - "github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-service/clock" "github.com/ethereum/go-ethereum/common" @@ -101,7 +100,7 @@ func setupMonitorTest(t *testing.T, allowedGames []common.Address) (*gameMonitor return i, nil } sched := &stubScheduler{} - monitor := newGameMonitor(logger, metrics.NoopMetrics, clock.SystemClock, source, sched, time.Duration(0), fetchBlockNum, allowedGames) + monitor := newGameMonitor(logger, clock.SystemClock, source, sched, time.Duration(0), fetchBlockNum, allowedGames) return monitor, source, sched } diff --git a/op-challenger/game/scheduler/coordinator.go b/op-challenger/game/scheduler/coordinator.go index 7d8d62f3e..eb620c0d8 100644 --- a/op-challenger/game/scheduler/coordinator.go +++ b/op-challenger/game/scheduler/coordinator.go @@ -5,6 +5,8 @@ import ( "errors" "fmt" + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "golang.org/x/exp/slices" @@ -17,7 +19,7 @@ type PlayerCreator func(address common.Address, dir string) (GamePlayer, error) type gameState struct { player GamePlayer inflight bool - resolved bool + status types.GameStatus } // coordinator manages the set of current games, queues games to be played (on separate worker threads) and @@ -31,6 +33,7 @@ type coordinator struct { resultQueue <-chan job logger log.Logger + m SchedulerMetricer createPlayer PlayerCreator states map[common.Address]*gameState disk DiskManager @@ -49,18 +52,35 @@ func (c *coordinator) schedule(ctx context.Context, games []common.Address) erro } } + var gamesInProgress int + var gamesChallengerWon int + var gamesDefenderWon int var errs []error + var jobs []job // Next collect all the jobs to schedule and ensure all games are recorded in the states map. // Otherwise, results may start being processed before all games are recorded, resulting in existing // data directories potentially being deleted for games that are required. - var jobs []job for _, addr := range games { if j, err := c.createJob(addr); err != nil { errs = append(errs, err) } else if j != nil { jobs = append(jobs, *j) } + state, ok := c.states[addr] + if ok { + switch state.status { + case types.GameStatusInProgress: + gamesInProgress++ + case types.GameStatusDefenderWon: + gamesDefenderWon++ + case types.GameStatusChallengerWon: + gamesChallengerWon++ + } + } else { + c.logger.Warn("Game not found in states map", "game", addr) + } } + c.m.RecordGamesStatus(gamesInProgress, gamesChallengerWon, gamesDefenderWon) // Finally, enqueue the jobs for _, j := range jobs { @@ -114,7 +134,7 @@ func (c *coordinator) processResult(j job) error { return fmt.Errorf("game %v received unexpected result: %w", j.addr, errUnknownGame) } state.inflight = false - state.resolved = j.resolved + state.status = j.status c.deleteResolvedGameFiles() return nil } @@ -122,7 +142,7 @@ func (c *coordinator) processResult(j job) error { func (c *coordinator) deleteResolvedGameFiles() { var keepGames []common.Address for addr, state := range c.states { - if !state.resolved || state.inflight { + if state.status == types.GameStatusInProgress || state.inflight { keepGames = append(keepGames, addr) } } @@ -131,9 +151,10 @@ func (c *coordinator) deleteResolvedGameFiles() { } } -func newCoordinator(logger log.Logger, jobQueue chan<- job, resultQueue <-chan job, createPlayer PlayerCreator, disk DiskManager) *coordinator { +func newCoordinator(logger log.Logger, m SchedulerMetricer, jobQueue chan<- job, resultQueue <-chan job, createPlayer PlayerCreator, disk DiskManager) *coordinator { return &coordinator{ logger: logger, + m: m, jobQueue: jobQueue, resultQueue: resultQueue, createPlayer: createPlayer, diff --git a/op-challenger/game/scheduler/coordinator_test.go b/op-challenger/game/scheduler/coordinator_test.go index cd1616818..f3c0f94a4 100644 --- a/op-challenger/game/scheduler/coordinator_test.go +++ b/op-challenger/game/scheduler/coordinator_test.go @@ -5,6 +5,8 @@ import ( "fmt" "testing" + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" @@ -140,7 +142,7 @@ func TestDeleteDataForResolvedGames(t *testing.T) { require.NoError(t, c.schedule(ctx, []common.Address{gameAddr3})) require.Len(t, workQueue, 1) j := <-workQueue - j.resolved = true + j.status = types.GameStatusDefenderWon require.NoError(t, c.processResult(j)) // But ensure its data directory is marked as existing disk.DirForGame(gameAddr3) @@ -155,7 +157,9 @@ func TestDeleteDataForResolvedGames(t *testing.T) { // Game 3 hasn't yet progressed (update is still in flight) for i := 0; i < len(gameAddrs)-1; i++ { j := <-workQueue - j.resolved = j.addr == gameAddr2 + if j.addr == gameAddr2 { + j.status = types.GameStatusDefenderWon + } require.NoError(t, c.processResult(j)) } @@ -229,20 +233,20 @@ func setupCoordinatorTest(t *testing.T, bufferSize int) (*coordinator, <-chan jo created: make(map[common.Address]*stubGame), } disk := &stubDiskManager{gameDirExists: make(map[common.Address]bool)} - c := newCoordinator(logger, workQueue, resultQueue, games.CreateGame, disk) + c := newCoordinator(logger, metrics.NoopMetrics, workQueue, resultQueue, games.CreateGame, disk) return c, workQueue, resultQueue, games, disk } type stubGame struct { addr common.Address progressCount int - done bool + status types.GameStatus dir string } -func (g *stubGame) ProgressGame(_ context.Context) bool { +func (g *stubGame) ProgressGame(_ context.Context) types.GameStatus { g.progressCount++ - return g.done + return g.status } type createdGames struct { @@ -259,10 +263,14 @@ func (c *createdGames) CreateGame(addr common.Address, dir string) (GamePlayer, if _, exists := c.created[addr]; exists { c.t.Fatalf("game %v already exists", addr) } + status := types.GameStatusInProgress + if addr == c.createCompleted { + status = types.GameStatusDefenderWon + } game := &stubGame{ - addr: addr, - done: addr == c.createCompleted, - dir: dir, + addr: addr, + status: status, + dir: dir, } c.created[addr] = game return game, nil diff --git a/op-challenger/game/scheduler/scheduler.go b/op-challenger/game/scheduler/scheduler.go index 819ec2a93..4e9e7c3fb 100644 --- a/op-challenger/game/scheduler/scheduler.go +++ b/op-challenger/game/scheduler/scheduler.go @@ -11,6 +11,10 @@ import ( var ErrBusy = errors.New("busy scheduling previous update") +type SchedulerMetricer interface { + RecordGamesStatus(inProgress, defenderWon, challengerWon int) +} + type Scheduler struct { logger log.Logger coordinator *coordinator @@ -22,7 +26,7 @@ type Scheduler struct { cancel func() } -func NewScheduler(logger log.Logger, disk DiskManager, maxConcurrency uint, createPlayer PlayerCreator) *Scheduler { +func NewScheduler(logger log.Logger, m SchedulerMetricer, disk DiskManager, maxConcurrency uint, createPlayer PlayerCreator) *Scheduler { // Size job and results queues to be fairly small so backpressure is applied early // but with enough capacity to keep the workers busy jobQueue := make(chan job, maxConcurrency*2) @@ -34,7 +38,7 @@ func NewScheduler(logger log.Logger, disk DiskManager, maxConcurrency uint, crea return &Scheduler{ logger: logger, - coordinator: newCoordinator(logger, jobQueue, resultQueue, createPlayer, disk), + coordinator: newCoordinator(logger, m, jobQueue, resultQueue, createPlayer, disk), maxConcurrency: maxConcurrency, scheduleQueue: scheduleQueue, jobQueue: jobQueue, diff --git a/op-challenger/game/scheduler/scheduler_test.go b/op-challenger/game/scheduler/scheduler_test.go index 2bf84703d..820cb3257 100644 --- a/op-challenger/game/scheduler/scheduler_test.go +++ b/op-challenger/game/scheduler/scheduler_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" @@ -18,7 +19,7 @@ func TestSchedulerProcessesGames(t *testing.T) { } removeExceptCalls := make(chan []common.Address) disk := &trackingDiskManager{removeExceptCalls: removeExceptCalls} - s := NewScheduler(logger, disk, 2, createPlayer) + s := NewScheduler(logger, metrics.NoopMetrics, disk, 2, createPlayer) s.Start(ctx) gameAddr1 := common.Address{0xaa} @@ -46,7 +47,7 @@ func TestReturnBusyWhenScheduleQueueFull(t *testing.T) { } removeExceptCalls := make(chan []common.Address) disk := &trackingDiskManager{removeExceptCalls: removeExceptCalls} - s := NewScheduler(logger, disk, 2, createPlayer) + s := NewScheduler(logger, metrics.NoopMetrics, disk, 2, createPlayer) // Scheduler not started - first call fills the queue require.NoError(t, s.Schedule([]common.Address{{0xaa}})) diff --git a/op-challenger/game/scheduler/types.go b/op-challenger/game/scheduler/types.go index 831ce1fc7..03fd96a87 100644 --- a/op-challenger/game/scheduler/types.go +++ b/op-challenger/game/scheduler/types.go @@ -4,10 +4,12 @@ import ( "context" "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum-optimism/optimism/op-challenger/game/types" ) type GamePlayer interface { - ProgressGame(ctx context.Context) bool + ProgressGame(ctx context.Context) types.GameStatus } type DiskManager interface { @@ -16,7 +18,7 @@ type DiskManager interface { } type job struct { - addr common.Address - player GamePlayer - resolved bool + addr common.Address + player GamePlayer + status types.GameStatus } diff --git a/op-challenger/game/scheduler/worker.go b/op-challenger/game/scheduler/worker.go index cd30b2978..55c53067b 100644 --- a/op-challenger/game/scheduler/worker.go +++ b/op-challenger/game/scheduler/worker.go @@ -15,7 +15,7 @@ func progressGames(ctx context.Context, in <-chan job, out chan<- job, wg *sync. case <-ctx.Done(): return case j := <-in: - j.resolved = j.player.ProgressGame(ctx) + j.status = j.player.ProgressGame(ctx) out <- j } } diff --git a/op-challenger/game/scheduler/worker_test.go b/op-challenger/game/scheduler/worker_test.go index 8d2c316a4..7c0b4091a 100644 --- a/op-challenger/game/scheduler/worker_test.go +++ b/op-challenger/game/scheduler/worker_test.go @@ -6,6 +6,8 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/stretchr/testify/require" ) @@ -20,17 +22,17 @@ func TestWorkerShouldProcessJobsUntilContextDone(t *testing.T) { go progressGames(ctx, in, out, &wg) in <- job{ - player: &stubPlayer{done: false}, + player: &stubPlayer{status: types.GameStatusInProgress}, } in <- job{ - player: &stubPlayer{done: true}, + player: &stubPlayer{status: types.GameStatusDefenderWon}, } result1 := readWithTimeout(t, out) result2 := readWithTimeout(t, out) - require.Equal(t, result1.resolved, false) - require.Equal(t, result2.resolved, true) + require.Equal(t, result1.status, types.GameStatusInProgress) + require.Equal(t, result2.status, types.GameStatusDefenderWon) // Cancel the context which should exit the worker cancel() @@ -38,11 +40,11 @@ func TestWorkerShouldProcessJobsUntilContextDone(t *testing.T) { } type stubPlayer struct { - done bool + status types.GameStatus } -func (s *stubPlayer) ProgressGame(ctx context.Context) bool { - return s.done +func (s *stubPlayer) ProgressGame(ctx context.Context) types.GameStatus { + return s.status } func readWithTimeout[T any](t *testing.T, ch <-chan T) T { diff --git a/op-challenger/game/service.go b/op-challenger/game/service.go index d176a559c..8ec157372 100644 --- a/op-challenger/game/service.go +++ b/op-challenger/game/service.go @@ -69,13 +69,14 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Se disk := newDiskManager(cfg.Datadir) sched := scheduler.NewScheduler( logger, + m, disk, cfg.MaxConcurrency, func(addr common.Address, dir string) (scheduler.GamePlayer, error) { return fault.NewGamePlayer(ctx, logger, m, cfg, dir, addr, txMgr, client) }) - monitor := newGameMonitor(logger, m, cl, loader, sched, cfg.GameWindow, client.BlockNumber, cfg.GameAllowlist) + monitor := newGameMonitor(logger, cl, loader, sched, cfg.GameWindow, client.BlockNumber, cfg.GameAllowlist) m.RecordInfo(version.SimpleWithMeta) m.RecordUp() diff --git a/op-challenger/game/types/types.go b/op-challenger/game/types/types.go new file mode 100644 index 000000000..4db2f3be1 --- /dev/null +++ b/op-challenger/game/types/types.go @@ -0,0 +1,35 @@ +package types + +import ( + "fmt" +) + +type GameStatus uint8 + +const ( + GameStatusInProgress GameStatus = iota + GameStatusChallengerWon + GameStatusDefenderWon +) + +// String returns the string representation of the game status. +func (s GameStatus) String() string { + switch s { + case GameStatusInProgress: + return "In Progress" + case GameStatusChallengerWon: + return "Challenger Won" + case GameStatusDefenderWon: + return "Defender Won" + default: + return "Unknown" + } +} + +// GameStatusFromUint8 returns a game status from the uint8 representation. +func GameStatusFromUint8(i uint8) (GameStatus, error) { + if i > 2 { + return GameStatus(i), fmt.Errorf("invalid game status: %d", i) + } + return GameStatus(i), nil +} diff --git a/op-challenger/game/types/types_test.go b/op-challenger/game/types/types_test.go new file mode 100644 index 000000000..b22425f4e --- /dev/null +++ b/op-challenger/game/types/types_test.go @@ -0,0 +1,30 @@ +package types + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +var validGameStatuses = []GameStatus{ + GameStatusInProgress, + GameStatusChallengerWon, + GameStatusDefenderWon, +} + +func TestGameStatusFromUint8(t *testing.T) { + for _, status := range validGameStatuses { + t.Run(fmt.Sprintf("Valid Game Status %v", status), func(t *testing.T) { + parsed, err := GameStatusFromUint8(uint8(status)) + require.NoError(t, err) + require.Equal(t, status, parsed) + }) + } + + t.Run("Invalid", func(t *testing.T) { + status, err := GameStatusFromUint8(3) + require.Error(t, err) + require.Equal(t, GameStatus(3), status) + }) +} diff --git a/op-challenger/metrics/metrics.go b/op-challenger/metrics/metrics.go index 240d595b3..6f8c5d1f4 100644 --- a/op-challenger/metrics/metrics.go +++ b/op-challenger/metrics/metrics.go @@ -24,6 +24,8 @@ type Metricer interface { RecordGameStep() RecordGameMove() RecordCannonExecutionTime(t float64) + + RecordGamesStatus(inProgress, defenderWon, challengerWon int) } type Metrics struct { @@ -36,9 +38,12 @@ type Metrics struct { info prometheus.GaugeVec up prometheus.Gauge - moves prometheus.Counter - steps prometheus.Counter + moves prometheus.Counter + steps prometheus.Counter + cannonExecutionTime prometheus.Histogram + + trackedGames prometheus.GaugeVec } var _ Metricer = (*Metrics)(nil) @@ -82,6 +87,13 @@ func NewMetrics() *Metrics { Help: "Time (in seconds) to execute cannon", Buckets: append([]float64{1.0, 10.0}, prometheus.ExponentialBuckets(30.0, 2.0, 14)...), }), + trackedGames: *factory.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: Namespace, + Name: "tracked_games", + Help: "Number of games being tracked by the challenger", + }, []string{ + "status", + }), } } @@ -120,3 +132,9 @@ func (m *Metrics) RecordGameStep() { func (m *Metrics) RecordCannonExecutionTime(t float64) { m.cannonExecutionTime.Observe(t) } + +func (m *Metrics) RecordGamesStatus(inProgress, defenderWon, challengerWon int) { + m.trackedGames.WithLabelValues("in_progress").Set(float64(inProgress)) + m.trackedGames.WithLabelValues("defender_won").Set(float64(defenderWon)) + m.trackedGames.WithLabelValues("challenger_won").Set(float64(challengerWon)) +} diff --git a/op-challenger/metrics/noop.go b/op-challenger/metrics/noop.go index 2b4f9e982..2aadfb2e1 100644 --- a/op-challenger/metrics/noop.go +++ b/op-challenger/metrics/noop.go @@ -10,8 +10,12 @@ type noopMetrics struct { var NoopMetrics Metricer = new(noopMetrics) -func (*noopMetrics) RecordInfo(version string) {} -func (*noopMetrics) RecordUp() {} -func (*noopMetrics) RecordGameMove() {} -func (*noopMetrics) RecordGameStep() {} +func (*noopMetrics) RecordInfo(version string) {} +func (*noopMetrics) RecordUp() {} + +func (*noopMetrics) RecordGameMove() {} +func (*noopMetrics) RecordGameStep() {} + func (*noopMetrics) RecordCannonExecutionTime(t float64) {} + +func (*noopMetrics) RecordGamesStatus(inProgress, defenderWon, challengerWon int) {} From 16500702854b7a0943ed0fb85a30f4da3ee8fa25 Mon Sep 17 00:00:00 2001 From: Andreas Bigger Date: Fri, 1 Sep 2023 10:11:13 -0400 Subject: [PATCH 25/59] Track in flight games inside the scheduler component. --- op-challenger/game/scheduler/coordinator.go | 2 ++ op-challenger/game/scheduler/scheduler.go | 2 ++ op-challenger/metrics/metrics.go | 30 ++++++++++++++++++--- op-challenger/metrics/noop.go | 3 +++ 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/op-challenger/game/scheduler/coordinator.go b/op-challenger/game/scheduler/coordinator.go index eb620c0d8..f90fca559 100644 --- a/op-challenger/game/scheduler/coordinator.go +++ b/op-challenger/game/scheduler/coordinator.go @@ -65,6 +65,7 @@ func (c *coordinator) schedule(ctx context.Context, games []common.Address) erro errs = append(errs, err) } else if j != nil { jobs = append(jobs, *j) + c.m.RecordGameUpdateScheduled() } state, ok := c.states[addr] if ok { @@ -136,6 +137,7 @@ func (c *coordinator) processResult(j job) error { state.inflight = false state.status = j.status c.deleteResolvedGameFiles() + c.m.RecordGameUpdateCompleted() return nil } diff --git a/op-challenger/game/scheduler/scheduler.go b/op-challenger/game/scheduler/scheduler.go index 4e9e7c3fb..41bf54b6e 100644 --- a/op-challenger/game/scheduler/scheduler.go +++ b/op-challenger/game/scheduler/scheduler.go @@ -13,6 +13,8 @@ var ErrBusy = errors.New("busy scheduling previous update") type SchedulerMetricer interface { RecordGamesStatus(inProgress, defenderWon, challengerWon int) + RecordGameUpdateScheduled() + RecordGameUpdateCompleted() } type Scheduler struct { diff --git a/op-challenger/metrics/metrics.go b/op-challenger/metrics/metrics.go index 6f8c5d1f4..004ad1af1 100644 --- a/op-challenger/metrics/metrics.go +++ b/op-challenger/metrics/metrics.go @@ -26,6 +26,9 @@ type Metricer interface { RecordCannonExecutionTime(t float64) RecordGamesStatus(inProgress, defenderWon, challengerWon int) + + RecordGameUpdateScheduled() + RecordGameUpdateCompleted() } type Metrics struct { @@ -43,7 +46,8 @@ type Metrics struct { cannonExecutionTime prometheus.Histogram - trackedGames prometheus.GaugeVec + trackedGames prometheus.GaugeVec + inflightGames prometheus.Gauge } var _ Metricer = (*Metrics)(nil) @@ -85,7 +89,9 @@ func NewMetrics() *Metrics { Namespace: Namespace, Name: "cannon_execution_time", Help: "Time (in seconds) to execute cannon", - Buckets: append([]float64{1.0, 10.0}, prometheus.ExponentialBuckets(30.0, 2.0, 14)...), + Buckets: append( + []float64{1.0, 10.0}, + prometheus.ExponentialBuckets(30.0, 2.0, 14)...), }), trackedGames: *factory.NewGaugeVec(prometheus.GaugeOpts{ Namespace: Namespace, @@ -94,6 +100,11 @@ func NewMetrics() *Metrics { }, []string{ "status", }), + inflightGames: factory.NewGauge(prometheus.GaugeOpts{ + Namespace: Namespace, + Name: "inflight_games", + Help: "Number of games being tracked by the challenger", + }), } } @@ -101,7 +112,12 @@ func (m *Metrics) Serve(ctx context.Context, host string, port int) error { return opmetrics.ListenAndServe(ctx, m.registry, host, port) } -func (m *Metrics) StartBalanceMetrics(ctx context.Context, l log.Logger, client *ethclient.Client, account common.Address) { +func (m *Metrics) StartBalanceMetrics( + ctx context.Context, + l log.Logger, + client *ethclient.Client, + account common.Address, +) { opmetrics.LaunchBalanceMetrics(ctx, l, m.registry, m.ns, client, account) } @@ -138,3 +154,11 @@ func (m *Metrics) RecordGamesStatus(inProgress, defenderWon, challengerWon int) m.trackedGames.WithLabelValues("defender_won").Set(float64(defenderWon)) m.trackedGames.WithLabelValues("challenger_won").Set(float64(challengerWon)) } + +func (m *Metrics) RecordGameUpdateScheduled() { + m.inflightGames.Add(1) +} + +func (m *Metrics) RecordGameUpdateCompleted() { + m.inflightGames.Sub(1) +} diff --git a/op-challenger/metrics/noop.go b/op-challenger/metrics/noop.go index 2aadfb2e1..d02bd594f 100644 --- a/op-challenger/metrics/noop.go +++ b/op-challenger/metrics/noop.go @@ -19,3 +19,6 @@ func (*noopMetrics) RecordGameStep() {} func (*noopMetrics) RecordCannonExecutionTime(t float64) {} func (*noopMetrics) RecordGamesStatus(inProgress, defenderWon, challengerWon int) {} + +func (*noopMetrics) RecordGameUpdateScheduled() {} +func (*noopMetrics) RecordGameUpdateCompleted() {} From 765e3ebe1a0eb157497943577f2ad7dc99f6b592 Mon Sep 17 00:00:00 2001 From: protolambda Date: Tue, 5 Sep 2023 22:21:00 +0200 Subject: [PATCH 26/59] op-node: implement runtime config reloading --- op-e2e/setup.go | 10 +++--- op-e2e/system_test.go | 45 +++++++++++++++++++++++++ op-node/flags/flags.go | 8 +++++ op-node/node/config.go | 6 ++++ op-node/node/node.go | 61 ++++++++++++++++++++++++++++++---- op-node/node/runtime_config.go | 4 +++ op-node/service.go | 7 ++-- 7 files changed, 127 insertions(+), 14 deletions(-) diff --git a/op-e2e/setup.go b/op-e2e/setup.go index dc055a5b6..a3dcd77d1 100644 --- a/op-e2e/setup.go +++ b/op-e2e/setup.go @@ -119,8 +119,9 @@ func DefaultSystemConfig(t *testing.T) SystemConfig { ListenPort: 0, EnableAdmin: true, }, - L1EpochPollInterval: time.Second * 2, - ConfigPersistence: &rollupNode.DisabledConfigPersistence{}, + L1EpochPollInterval: time.Second * 2, + RuntimeConfigReloadInterval: time.Minute * 10, + ConfigPersistence: &rollupNode.DisabledConfigPersistence{}, }, "verifier": { Driver: driver.Config{ @@ -128,8 +129,9 @@ func DefaultSystemConfig(t *testing.T) SystemConfig { SequencerConfDepth: 0, SequencerEnabled: false, }, - L1EpochPollInterval: time.Second * 4, - ConfigPersistence: &rollupNode.DisabledConfigPersistence{}, + L1EpochPollInterval: time.Second * 4, + RuntimeConfigReloadInterval: time.Minute * 10, + ConfigPersistence: &rollupNode.DisabledConfigPersistence{}, }, }, Loggers: map[string]log.Logger{ diff --git a/op-e2e/system_test.go b/op-e2e/system_test.go index ae4255254..c17148cef 100644 --- a/op-e2e/system_test.go +++ b/op-e2e/system_test.go @@ -1388,3 +1388,48 @@ func TestPendingBlockIsLatest(t *testing.T) { t.Fatal("failed to get pending header with same number as latest header") }) } + +func TestRuntimeConfigReload(t *testing.T) { + InitParallel(t) + + cfg := DefaultSystemConfig(t) + // to speed up the test, make it reload the config more often, and do not impose a long conf depth + cfg.Nodes["verifier"].RuntimeConfigReloadInterval = time.Second * 5 + cfg.Nodes["verifier"].Driver.VerifierConfDepth = 1 + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + defer sys.Close() + initialRuntimeConfig := sys.RollupNodes["verifier"].RuntimeConfig() + + // close the EL node, since we want to block derivation, to solely rely on the reloading mechanism for updates. + sys.EthInstances["verifier"].Close() + + l1 := sys.Clients["l1"] + + // Change the system-config via L1 + sysCfgContract, err := bindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1) + require.NoError(t, err) + newUnsafeBlocksSigner := common.Address{0x12, 0x23, 0x45} + require.NotEqual(t, initialRuntimeConfig.P2PSequencerAddress(), newUnsafeBlocksSigner, "changing to a different address") + opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) + require.Nil(t, err) + // the unsafe signer address is part of the runtime config + tx, err := sysCfgContract.SetUnsafeBlockSigner(opts, newUnsafeBlocksSigner) + require.NoError(t, err) + + // wait for the change to confirm + receipt, err := bind.WaitMined(context.Background(), l1, tx) + require.NoError(t, err) + require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) + + // wait for the address to change + _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { + v := sys.RollupNodes["verifier"].RuntimeConfig().P2PSequencerAddress() + if v == newUnsafeBlocksSigner { + return struct{}{}, nil + } + return struct{}{}, fmt.Errorf("no change yet, seeing %s but looking for %s", v, newUnsafeBlocksSigner) + }) + require.NoError(t, err) +} diff --git a/op-node/flags/flags.go b/op-node/flags/flags.go index f600afce3..5dcc78ddf 100644 --- a/op-node/flags/flags.go +++ b/op-node/flags/flags.go @@ -146,6 +146,13 @@ var ( Required: false, Value: time.Second * 12 * 32, } + RuntimeConfigReloadIntervalFlag = &cli.DurationFlag{ + Name: "l1.runtime-config-reload-interval", + Usage: "Poll interval for reloading the runtime config, useful when config events are not being picked up. Disabled if 0 or negative.", + EnvVars: prefixEnvVars("L1_RUNTIME_CONFIG_RELOAD_INTERVAL"), + Required: false, + Value: time.Minute * 10, + } MetricsEnabledFlag = &cli.BoolFlag{ Name: "metrics.enabled", Usage: "Enable the metrics server", @@ -261,6 +268,7 @@ var optionalFlags = []cli.Flag{ SequencerMaxSafeLagFlag, SequencerL1Confs, L1EpochPollIntervalFlag, + RuntimeConfigReloadIntervalFlag, RPCEnableAdmin, RPCAdminPersistence, MetricsEnabledFlag, diff --git a/op-node/node/config.go b/op-node/node/config.go index c46834d5c..8e79c21a3 100644 --- a/op-node/node/config.go +++ b/op-node/node/config.go @@ -41,6 +41,12 @@ type Config struct { ConfigPersistence ConfigPersistence + // RuntimeConfigReloadInterval defines the interval between runtime config reloads. + // Disabled if 0. + // Runtime config changes should be picked up from log-events, + // but if log-events are not coming in (e.g. not syncing blocks) then the reload ensures the config stays accurate. + RuntimeConfigReloadInterval time.Duration + // Optional Tracer Tracer Heartbeat HeartbeatConfig diff --git a/op-node/node/node.go b/op-node/node/node.go index 8adfa754e..e27a1ff52 100644 --- a/op-node/node/node.go +++ b/op-node/node/node.go @@ -2,7 +2,6 @@ package node import ( "context" - "errors" "fmt" "time" @@ -19,6 +18,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup/driver" "github.com/ethereum-optimism/optimism/op-node/sources" "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/retry" ) type OpNode struct { @@ -159,27 +159,70 @@ func (n *OpNode) initRuntimeConfig(ctx context.Context, cfg *Config) error { // attempt to load runtime config, repeat N times n.runCfg = NewRuntimeConfig(n.log, n.l1Source, &cfg.Rollup) - for i := 0; i < 5; i++ { + confDepth := cfg.Driver.VerifierConfDepth + reload := func(ctx context.Context) (eth.L1BlockRef, error) { fetchCtx, fetchCancel := context.WithTimeout(ctx, time.Second*10) l1Head, err := n.l1Source.L1BlockRefByLabel(fetchCtx, eth.Unsafe) fetchCancel() if err != nil { n.log.Error("failed to fetch L1 head for runtime config initialization", "err", err) - continue + return eth.L1BlockRef{}, err + } + + // Apply confirmation-distance + blNum := l1Head.Number + if blNum >= confDepth { + blNum -= confDepth + } + fetchCtx, fetchCancel = context.WithTimeout(ctx, time.Second*10) + confirmed, err := n.l1Source.L1BlockRefByNumber(fetchCtx, blNum) + fetchCancel() + if err != nil { + n.log.Error("failed to fetch confirmed L1 block for runtime config loading", "err", err, "number", blNum) + return eth.L1BlockRef{}, err } fetchCtx, fetchCancel = context.WithTimeout(ctx, time.Second*10) - err = n.runCfg.Load(fetchCtx, l1Head) + err = n.runCfg.Load(fetchCtx, confirmed) fetchCancel() if err != nil { n.log.Error("failed to fetch runtime config data", "err", err) - continue + return l1Head, err } + return l1Head, nil + } - return nil + // initialize the runtime config before unblocking + if _, err := retry.Do(ctx, 5, retry.Fixed(time.Second*10), func() (eth.L1BlockRef, error) { + return reload(ctx) + }); err != nil { + return fmt.Errorf("failed to load runtime configuration repeatedly, last error: %w", err) } - return errors.New("failed to load runtime configuration repeatedly") + // start a background loop, to keep reloading it every 10 minutes + go func(ctx context.Context, reloadInterval time.Duration) { + if reloadInterval <= 0 { + n.log.Debug("not running runtime-config reloading background loop") + return + } + ticker := time.NewTicker(reloadInterval) + defer ticker.Stop() + for { + select { + case <-ticker.C: + // If the reload fails, we will try again the next interval. + // Missing a runtime-config update is not critical, and we do not want to overwhelm the L1 RPC. + if l1Head, err := reload(ctx); err != nil { + n.log.Warn("failed to reload runtime config", "err", err) + } else { + n.log.Debug("reloaded runtime config", "l1_head", l1Head) + } + case <-ctx.Done(): + return + } + } + }(n.resourcesCtx, cfg.RuntimeConfigReloadInterval) // this keeps running after initialization + return nil } func (n *OpNode) initL2(ctx context.Context, cfg *Config, snapshotLog log.Logger) error { @@ -397,6 +440,10 @@ func (n *OpNode) P2P() p2p.Node { return n.p2pNode } +func (n *OpNode) RuntimeConfig() ReadonlyRuntimeConfig { + return n.runCfg +} + // Close closes all resources. func (n *OpNode) Close() error { var result *multierror.Error diff --git a/op-node/node/runtime_config.go b/op-node/node/runtime_config.go index b95d4dc34..6be09b1a7 100644 --- a/op-node/node/runtime_config.go +++ b/op-node/node/runtime_config.go @@ -23,6 +23,10 @@ type RuntimeCfgL1Source interface { ReadStorageAt(ctx context.Context, address common.Address, storageSlot common.Hash, blockHash common.Hash) (common.Hash, error) } +type ReadonlyRuntimeConfig interface { + P2PSequencerAddress() common.Address +} + // RuntimeConfig maintains runtime-configurable options. // These options are loaded based on initial loading + updates for every subsequent L1 block. // Only the *latest* values are maintained however, the runtime config has no concept of chain history, diff --git a/op-node/service.go b/op-node/service.go index e7e9f22df..21c230fce 100644 --- a/op-node/service.go +++ b/op-node/service.go @@ -82,9 +82,10 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { ListenAddr: ctx.String(flags.PprofAddrFlag.Name), ListenPort: ctx.Int(flags.PprofPortFlag.Name), }, - P2P: p2pConfig, - P2PSigner: p2pSignerSetup, - L1EpochPollInterval: ctx.Duration(flags.L1EpochPollIntervalFlag.Name), + P2P: p2pConfig, + P2PSigner: p2pSignerSetup, + L1EpochPollInterval: ctx.Duration(flags.L1EpochPollIntervalFlag.Name), + RuntimeConfigReloadInterval: ctx.Duration(flags.RuntimeConfigReloadIntervalFlag.Name), Heartbeat: node.HeartbeatConfig{ Enabled: ctx.Bool(flags.HeartbeatEnabledFlag.Name), Moniker: ctx.String(flags.HeartbeatMonikerFlag.Name), From 462cc3166c66ae2552d3c819e906c4d5f8a2743d Mon Sep 17 00:00:00 2001 From: Hamdi Allam Date: Tue, 5 Sep 2023 20:30:35 -0400 Subject: [PATCH 27/59] fix bridge processor height detection on startup --- indexer/database/blocks.go | 2 +- indexer/database/bridge_transactions.go | 56 +++++++++++++ indexer/etl/l1_etl.go | 4 +- indexer/processors/bridge.go | 70 +++++++++-------- .../processors/bridge/l1_bridge_processor.go | 78 ------------------- .../processors/bridge/l2_bridge_processor.go | 70 ----------------- 6 files changed, 98 insertions(+), 182 deletions(-) diff --git a/indexer/database/blocks.go b/indexer/database/blocks.go index 628b66f62..a8f2bde6d 100644 --- a/indexer/database/blocks.go +++ b/indexer/database/blocks.go @@ -233,7 +233,7 @@ func (db *blocksDB) LatestEpoch() (*Epoch, error) { // L2 for a faster query. Per the protocol, the L2 block that starts a new epoch // will have a matching timestamp with the L1 origin. query := db.gorm.Table("l1_block_headers").Order("l1_block_headers.timestamp DESC") - query = query.Joins("INNER JOIN l2_block_headers ON l1_block_headers.timestamp = l2_block_headers.timestamp") + query = query.Joins("INNER JOIN l2_block_headers ON l2_block_headers.timestamp = l1_block_headers.timestamp") query = query.Select("*") var epoch Epoch diff --git a/indexer/database/bridge_transactions.go b/indexer/database/bridge_transactions.go index a9c7d374b..c5472cc44 100644 --- a/indexer/database/bridge_transactions.go +++ b/indexer/database/bridge_transactions.go @@ -47,7 +47,10 @@ type L2TransactionWithdrawal struct { type BridgeTransactionsView interface { L1TransactionDeposit(common.Hash) (*L1TransactionDeposit, error) + L1LatestBlockHeader() (*L1BlockHeader, error) + L2TransactionWithdrawal(common.Hash) (*L2TransactionWithdrawal, error) + L2LatestBlockHeader() (*L2BlockHeader, error) } type BridgeTransactionsDB interface { @@ -94,6 +97,37 @@ func (db *bridgeTransactionsDB) L1TransactionDeposit(sourceHash common.Hash) (*L return &deposit, nil } +func (db *bridgeTransactionsDB) L1LatestBlockHeader() (*L1BlockHeader, error) { + // Markers for an indexed bridge event + // L1: Latest Transaction Deposit, Latest Proven/Finalized Withdrawal + l1DepositQuery := db.gorm.Table("l1_transaction_deposits").Order("l1_transaction_deposits.timestamp DESC").Limit(1) + l1DepositQuery = l1DepositQuery.Joins("INNER JOIN l1_contract_events ON l1_contract_events.guid = l1_transaction_deposits.initiated_l1_event_guid") + l1DepositQuery = l1DepositQuery.Select("l1_contract_events.*") + + l1ProvenQuery := db.gorm.Table("l2_transaction_withdrawals") + l1ProvenQuery = l1ProvenQuery.Joins("INNER JOIN l1_contract_events ON l1_contract_events.guid = l2_transaction_withdrawals.proven_l1_event_guid") + l1ProvenQuery = l1ProvenQuery.Order("l1_contract_events.timestamp DESC").Select("l1_contract_events.*").Limit(1) + + l1FinalizedQuery := db.gorm.Table("l2_transaction_withdrawals") + l1FinalizedQuery = l1FinalizedQuery.Joins("INNER JOIN l1_contract_events ON l1_contract_events.guid = l2_transaction_withdrawals.proven_l1_event_guid") + l1FinalizedQuery = l1FinalizedQuery.Order("l1_contract_events.timestamp DESC").Select("l1_contract_events.*").Limit(1) + + l1Query := db.gorm.Table("((?) UNION (?) UNION (?)) AS latest_bridge_events", l1DepositQuery.Limit(1), l1ProvenQuery, l1FinalizedQuery) + l1Query = l1Query.Joins("INNER JOIN l1_block_headers ON l1_block_headers.hash = latest_bridge_events.block_hash") + l1Query = l1Query.Order("l1_block_headers.number DESC").Select("l1_block_headers.*") + + var l1Header L1BlockHeader + result := l1Query.Take(&l1Header) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, result.Error + } + + return &l1Header, nil +} + /** * Transactions withdrawn from L2 */ @@ -149,3 +183,25 @@ func (db *bridgeTransactionsDB) MarkL2TransactionWithdrawalFinalizedEvent(withdr result := db.gorm.Save(&withdrawal) return result.Error } + +func (db *bridgeTransactionsDB) L2LatestBlockHeader() (*L2BlockHeader, error) { + // L2: Inclusion of the latest deposit + l1DepositQuery := db.gorm.Table("l1_transaction_deposits").Order("l1_transaction_deposits.timestamp DESC") + l1DepositQuery = l1DepositQuery.Joins("INNER JOIN l1_contract_events ON l1_contract_events.guid = l1_transaction_deposits.initiated_l1_event_guid") + l1DepositQuery = l1DepositQuery.Select("l1_contract_events.*") + + l2Query := db.gorm.Table("(?) AS l1_deposit_events", l1DepositQuery) + l2Query = l2Query.Joins("INNER JOIN l2_block_headers ON l2_block_headers.timestamp = l1_deposit_events.timestamp") + l2Query = l2Query.Select("l2_block_headers.*") + + var l2Header L2BlockHeader + result := l2Query.Take(&l2Header) + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, nil + } + return nil, result.Error + } + + return &l2Header, nil +} diff --git a/indexer/etl/l1_etl.go b/indexer/etl/l1_etl.go index 20b70ca2d..56892aafb 100644 --- a/indexer/etl/l1_etl.go +++ b/indexer/etl/l1_etl.go @@ -44,7 +44,7 @@ func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli fromHeader = latestHeader.RLPHeader.Header() } else if cfg.StartHeight.BitLen() > 0 { - log.Info("no indexed state in storage, starting from supplied L1 height", "height", cfg.StartHeight.String()) + log.Info("no indexed state starting from supplied L1 height", "height", cfg.StartHeight.String()) header, err := client.BlockHeaderByNumber(cfg.StartHeight) if err != nil { return nil, fmt.Errorf("could not fetch starting block header: %w", err) @@ -53,7 +53,7 @@ func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli fromHeader = header } else { - log.Info("no indexed state in storage, starting from L1 genesis") + log.Info("no indexed state, starting from genesis") } // NOTE - The use of un-buffered channel here assumes that downstream consumers diff --git a/indexer/processors/bridge.go b/indexer/processors/bridge.go index 8f16a0a98..f1aad93fd 100644 --- a/indexer/processors/bridge.go +++ b/indexer/processors/bridge.go @@ -29,35 +29,32 @@ type BridgeProcessor struct { func NewBridgeProcessor(log log.Logger, db *database.DB, l1Etl *etl.L1ETL, chainConfig config.ChainConfig) (*BridgeProcessor, error) { log = log.New("processor", "bridge") - latestL1Header, err := bridge.L1LatestBridgeEventHeader(db, chainConfig) + latestL1Header, err := db.BridgeTransactions.L1LatestBlockHeader() if err != nil { return nil, err } - latestL2Header, err := bridge.L2LatestBridgeEventHeader(db) + latestL2Header, err := db.BridgeTransactions.L2LatestBlockHeader() if err != nil { return nil, err } - // Since the bridge processor indexes events based on epochs, there's - // no scenario in which we have indexed L2 data with no L1 data. - // - // NOTE: Technically there is an exception if our bridging contracts are - // used to bridges native from L2 and an op-chain happens to launch where - // only L2 native bridge events have occurred. This is a rare situation now - // and it's worth the assertion as an integrity check. We can revisit this - // as more chains launch with primarily L2-native activity. - if latestL1Header == nil && latestL2Header != nil { - log.Error("detected indexed L2 bridge activity with no indexed L1 state", "l2_block_number", latestL2Header.Number) - return nil, errors.New("detected indexed L2 bridge activity with no indexed L1 state") - } - + var l1Header, l2Header *types.Header if latestL1Header == nil && latestL2Header == nil { - log.Info("no indexed state, starting from genesis") + log.Info("no indexed state, starting from rollup genesis") } else { - log.Info("detected the latest indexed state", "l1_block_number", latestL1Header.Number, "l2_block_number", latestL2Header.Number) + l1Height, l2Height := big.NewInt(0), big.NewInt(0) + if latestL1Header != nil { + l1Height = latestL1Header.Number + l1Header = latestL1Header.RLPHeader.Header() + } + if latestL2Header != nil { + l2Height = latestL2Header.Number + l2Header = latestL2Header.RLPHeader.Header() + } + log.Info("detected latest indexed state", "l1_block_number", l1Height, "l2_block_number", l2Height) } - return &BridgeProcessor{log, db, l1Etl, chainConfig, latestL1Header, latestL2Header}, nil + return &BridgeProcessor{log, db, l1Etl, chainConfig, l1Header, l2Header}, nil } func (b *BridgeProcessor) Start(ctx context.Context) error { @@ -83,29 +80,40 @@ func (b *BridgeProcessor) Start(ctx context.Context) error { latestEpoch, err := b.db.Blocks.LatestEpoch() if err != nil { return err - } - if latestEpoch == nil { - if b.LatestL1Header != nil { - // Once we have some state `latestEpoch` should never return nil. - b.log.Error("started with indexed bridge state, but no latest epoch returned", "latest_bridge_l1_block_number", b.LatestL1Header.Number) - return errors.New("started with indexed bridge state, but no blocks epochs returned") - } else { - b.log.Warn("no indexed epochs. waiting...") - continue + } else if latestEpoch == nil { + if b.LatestL1Header != nil || b.LatestL2Header != nil { + // Once we have some indexed state `latestEpoch` can never return nil + b.log.Error("bridge events indexed, but no indexed epoch returned", "latest_bridge_l1_block_number", b.LatestL1Header.Number) + return errors.New("bridge events indexed, but no indexed epoch returned") } + + b.log.Warn("no indexed epochs available. waiting...") + continue } + // Integrity Checks + if b.LatestL1Header != nil && latestEpoch.L1BlockHeader.Hash == b.LatestL1Header.Hash() { - // Marked as a warning since the bridge should always be processing at least 1 new epoch - b.log.Warn("all available epochs indexed by the bridge", "latest_epoch_number", b.LatestL1Header.Number) + b.log.Warn("all available epochs indexed", "latest_bridge_l1_block_number", b.LatestL1Header.Number) continue } + if b.LatestL1Header != nil && latestEpoch.L1BlockHeader.Number.Cmp(b.LatestL1Header.Number) <= 0 { + b.log.Error("non-increasing l1 block height observed", "latest_bridge_l1_block_number", b.LatestL1Header.Number, "latest_epoch_number", latestEpoch.L1BlockHeader.Number) + return errors.New("non-increasing l1 block heght observed") + } + if b.LatestL2Header != nil && latestEpoch.L2BlockHeader.Number.Cmp(b.LatestL2Header.Number) <= 0 { + b.log.Error("non-increasing l2 block height observed", "latest_bridge_l2_block_number", b.LatestL2Header.Number, "latest_epoch_number", latestEpoch.L2BlockHeader.Number) + return errors.New("non-increasing l2 block heght observed") + } + + // Process Bridge Events toL1Height, toL2Height := latestEpoch.L1BlockHeader.Number, latestEpoch.L2BlockHeader.Number fromL1Height, fromL2Height := big.NewInt(0), big.NewInt(0) if b.LatestL1Header != nil { - // `NewBridgeProcessor` ensures that LatestL2Header must not be nil if LatestL1Header is set fromL1Height = new(big.Int).Add(b.LatestL1Header.Number, big.NewInt(1)) + } + if b.LatestL2Header != nil { fromL2Height = new(big.Int).Add(b.LatestL2Header.Number, big.NewInt(1)) } @@ -139,7 +147,7 @@ func (b *BridgeProcessor) Start(ctx context.Context) error { // Try again on a subsequent interval batchLog.Error("unable to index new bridge events", "err", err) } else { - batchLog.Info("done indexing new bridge events", "latest_l1_block_number", toL1Height, "latest_l2_block_number", toL2Height) + batchLog.Info("done indexing bridge events", "latest_l1_block_number", toL1Height, "latest_l2_block_number", toL2Height) b.LatestL1Header = latestEpoch.L1BlockHeader.RLPHeader.Header() b.LatestL2Header = latestEpoch.L2BlockHeader.RLPHeader.Header() } diff --git a/indexer/processors/bridge/l1_bridge_processor.go b/indexer/processors/bridge/l1_bridge_processor.go index 711d17c63..8d82719b8 100644 --- a/indexer/processors/bridge/l1_bridge_processor.go +++ b/indexer/processors/bridge/l1_bridge_processor.go @@ -8,7 +8,6 @@ import ( "github.com/ethereum-optimism/optimism/indexer/config" "github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/processors/contracts" - "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" @@ -233,80 +232,3 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, chainConfig // a-ok! return nil } - -// L1LatestBridgeEventHeader returns the latest header for which and on-chain event -// has been observed on L1 -- Both initiated L1 events and finalization markers on L2. -func L1LatestBridgeEventHeader(db *database.DB, chainConfig config.ChainConfig) (*types.Header, error) { - portalAbi, err := bindings.OptimismPortalMetaData.GetAbi() - if err != nil { - return nil, err - } - - depositEventID := portalAbi.Events["TransactionDeposited"].ID - provenEventID := portalAbi.Events["WithdrawalProven"].ID - finalizedEventID := portalAbi.Events["WithdrawalFinalized"].ID - - // (1) Initiated L1 Events - // Since all initaited bridge events eventually reach the OptimismPortal to - // conduct the deposit, we can simply look for the last deposited transaction - // event on L2. - var latestDepositHeader *types.Header - contractEventFilter := database.ContractEvent{ContractAddress: chainConfig.L1Contracts.OptimismPortalProxy, EventSignature: depositEventID} - depositEvent, err := db.ContractEvents.L1LatestContractEventWithFilter(contractEventFilter) - if err != nil { - return nil, err - } - if depositEvent != nil { - l1BlockHeader, err := db.Blocks.L1BlockHeader(depositEvent.BlockHash) - if err != nil { - return nil, err - } - if l1BlockHeader != nil { - latestDepositHeader = l1BlockHeader.RLPHeader.Header() - } - } - - // (2) Finalization markers for L2 - // Like initiated L1 events, all withdrawals must flow through the OptimismPortal - // contract. We must look for both proven and finalized withdrawal events. - var latestWithdrawHeader *types.Header - contractEventFilter.EventSignature = finalizedEventID - withdrawEvent, err := db.ContractEvents.L1LatestContractEventWithFilter(contractEventFilter) - if err != nil { - return nil, err - } - if withdrawEvent != nil { - // Check if a have a later detected proven event - contractEventFilter.EventSignature = provenEventID - provenEvent, err := db.ContractEvents.L1LatestContractEventWithFilter(contractEventFilter) - if err != nil { - return nil, err - } - if provenEvent != nil && provenEvent.Timestamp > withdrawEvent.Timestamp { - withdrawEvent = provenEvent - } - - l1BlockHeader, err := db.Blocks.L1BlockHeader(withdrawEvent.BlockHash) - if err != nil { - return nil, err - } - latestWithdrawHeader = l1BlockHeader.RLPHeader.Header() - } - - if latestDepositHeader == nil { - // If there has been no seen deposits yet, there could have been no seen withdrawals - if latestWithdrawHeader != nil { - return nil, errors.New("detected an indexed withdrawal without any deposits") - } - return nil, nil - } else if latestWithdrawHeader == nil { - return latestDepositHeader, nil - } else { - // both deposits & withdrawals have occurred - if latestDepositHeader.Time > latestWithdrawHeader.Time { - return latestDepositHeader, nil - } else { - return latestWithdrawHeader, nil - } - } -} diff --git a/indexer/processors/bridge/l2_bridge_processor.go b/indexer/processors/bridge/l2_bridge_processor.go index 2e68605d7..803f3a2fc 100644 --- a/indexer/processors/bridge/l2_bridge_processor.go +++ b/indexer/processors/bridge/l2_bridge_processor.go @@ -7,10 +7,8 @@ import ( "github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/processors/contracts" - "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" ) @@ -182,71 +180,3 @@ func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, fromHeight // a-ok! return nil } - -// L2LatestBridgeEventHeader returns the latest header for which and on-chain event -// has been observed on L2 -- Both initiated L2 events and finalization markers from L1. -func L2LatestBridgeEventHeader(db *database.DB) (*types.Header, error) { - l2ToL1MessagePasserAbi, err := bindings.L2ToL1MessagePasserMetaData.GetAbi() - if err != nil { - return nil, err - } - crossDomainMessengerAbi, err := bindings.CrossDomainMessengerMetaData.GetAbi() - if err != nil { - return nil, err - } - - messagePassedID := l2ToL1MessagePasserAbi.Events["MessagePassed"].ID - relayedEventID := crossDomainMessengerAbi.Events["RelayedMessage"].ID - - // (1) Initiated L2 Events - // Since all initiated bridge events eventually reach the L2ToL1MessagePasser to - // initiate the withdrawal, we can simply look for the last message passed from - // this cont - var latestWithdrawHeader *types.Header - contractEventFilter := database.ContractEvent{ContractAddress: predeploys.L2ToL1MessagePasserAddr, EventSignature: messagePassedID} - withdrawEvent, err := db.ContractEvents.L2LatestContractEventWithFilter(contractEventFilter) - if err != nil { - return nil, err - } - if withdrawEvent != nil { - l2BlockHeader, err := db.Blocks.L2BlockHeader(withdrawEvent.BlockHash) - if err != nil { - return nil, err - } - if l2BlockHeader != nil { - latestWithdrawHeader = l2BlockHeader.RLPHeader.Header() - } - } - - // (2) Finalization markers for L1 - // Since deposited transactions from L1 are apart of the block derivation process, - // there are no native finalization markers for OptimismPortal#TransactionDeposited. - // The lowest layer to check for here is the CrossDomainMessenger#RelayedMessage event. - // This also converts the StandardBridge which simply is an extension of the messenger. - var latestRelayedMessageHeader *types.Header - contractEventFilter = database.ContractEvent{ContractAddress: predeploys.L2CrossDomainMessengerAddr, EventSignature: relayedEventID} - relayedEvent, err := db.ContractEvents.L2LatestContractEventWithFilter(contractEventFilter) - if err != nil { - return nil, err - } - if relayedEvent != nil { - l2BlockHeader, err := db.Blocks.L2BlockHeader(relayedEvent.BlockHash) - if err != nil { - return nil, err - } - if l2BlockHeader != nil { - latestRelayedMessageHeader = l2BlockHeader.RLPHeader.Header() - } - } - - // No causaal relationship between withdraw and relayed messages - if latestWithdrawHeader == nil || latestRelayedMessageHeader == nil { - return nil, nil - } else { - if latestWithdrawHeader.Time > latestRelayedMessageHeader.Time { - return latestWithdrawHeader, nil - } else { - return latestRelayedMessageHeader, nil - } - } -} From 882e801191d51131bb51f79333f96f97baade6cf Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Tue, 5 Sep 2023 13:21:02 +1000 Subject: [PATCH 28/59] op-e2e: Move geth wait utils to e2eutils --- op-e2e/bridge_test.go | 13 +++-- op-e2e/e2eutils/geth/wait.go | 107 +++++++++++++++++++++++++++++++++++ op-e2e/geth.go | 99 -------------------------------- op-e2e/setup.go | 3 +- op-e2e/system_fpp_test.go | 3 +- op-e2e/system_test.go | 19 ++++--- op-e2e/system_tob_test.go | 17 +++--- op-e2e/tx_helper.go | 9 +-- op-e2e/withdrawal_helper.go | 9 +-- 9 files changed, 147 insertions(+), 132 deletions(-) create mode 100644 op-e2e/e2eutils/geth/wait.go diff --git a/op-e2e/bridge_test.go b/op-e2e/bridge_test.go index 42a3c4a1b..0171738b2 100644 --- a/op-e2e/bridge_test.go +++ b/op-e2e/bridge_test.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -40,14 +41,14 @@ func TestERC20BridgeDeposits(t *testing.T) { // Deploy WETH9 weth9Address, tx, WETH9, err := bindings.DeployWETH9(opts, l1Client) require.NoError(t, err) - _, err = waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + _, err = geth.WaitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.NoError(t, err, "Waiting for deposit tx on L1") // Get some WETH opts.Value = big.NewInt(params.Ether) tx, err = WETH9.Fallback(opts, []byte{}) require.NoError(t, err) - _, err = waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + _, err = geth.WaitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.NoError(t, err) opts.Value = nil wethBalance, err := WETH9.BalanceOf(&bind.CallOpts{}, opts.From) @@ -61,7 +62,7 @@ func TestERC20BridgeDeposits(t *testing.T) { require.NoError(t, err) tx, err = optimismMintableTokenFactory.CreateOptimismMintableERC20(l2Opts, weth9Address, "L2-WETH", "L2-WETH") require.NoError(t, err) - _, err = waitForTransaction(tx.Hash(), l2Client, 3*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) + _, err = geth.WaitForTransaction(tx.Hash(), l2Client, 3*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) require.NoError(t, err) // Get the deployment event to have access to the L2 WETH9 address @@ -76,7 +77,7 @@ func TestERC20BridgeDeposits(t *testing.T) { // Approve WETH9 with the bridge tx, err = WETH9.Approve(opts, cfg.L1Deployments.L1StandardBridgeProxy, new(big.Int).SetUint64(math.MaxUint64)) require.NoError(t, err) - _, err = waitForTransaction(tx.Hash(), l1Client, 6*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + _, err = geth.WaitForTransaction(tx.Hash(), l1Client, 6*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.NoError(t, err) // Bridge the WETH9 @@ -84,7 +85,7 @@ func TestERC20BridgeDeposits(t *testing.T) { require.NoError(t, err) tx, err = l1StandardBridge.BridgeERC20(opts, weth9Address, event.LocalToken, big.NewInt(100), 100000, []byte{}) require.NoError(t, err) - depositReceipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + depositReceipt, err := geth.WaitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.NoError(t, err) t.Log("Deposit through L1StandardBridge", "gas used", depositReceipt.GasUsed) @@ -103,7 +104,7 @@ func TestERC20BridgeDeposits(t *testing.T) { depositTx, err := derive.UnmarshalDepositLogEvent(&depositEvent.Raw) require.NoError(t, err) - _, err = waitForTransaction(types.NewTx(depositTx).Hash(), l2Client, 3*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) + _, err = geth.WaitForTransaction(types.NewTx(depositTx).Hash(), l2Client, 3*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) require.NoError(t, err) // Ensure that the deposit went through diff --git a/op-e2e/e2eutils/geth/wait.go b/op-e2e/e2eutils/geth/wait.go new file mode 100644 index 000000000..7676ce6ef --- /dev/null +++ b/op-e2e/e2eutils/geth/wait.go @@ -0,0 +1,107 @@ +package geth + +import ( + "context" + "errors" + "fmt" + "math/big" + "time" + + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" +) + +var ( + // errTimeout represents a timeout + errTimeout = errors.New("timeout") +) + +func WaitForL1OriginOnL2(l1BlockNum uint64, client *ethclient.Client, timeout time.Duration) (*types.Block, error) { + timeoutCh := time.After(timeout) + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + + headChan := make(chan *types.Header, 100) + headSub, err := client.SubscribeNewHead(ctx, headChan) + if err != nil { + return nil, err + } + defer headSub.Unsubscribe() + + for { + select { + case head := <-headChan: + block, err := client.BlockByNumber(ctx, head.Number) + if err != nil { + return nil, err + } + l1Info, err := derive.L1InfoDepositTxData(block.Transactions()[0].Data()) + if err != nil { + return nil, err + } + if l1Info.Number >= l1BlockNum { + return block, nil + } + + case err := <-headSub.Err(): + return nil, fmt.Errorf("error in head subscription: %w", err) + case <-timeoutCh: + return nil, errTimeout + } + } +} + +func WaitForTransaction(hash common.Hash, client *ethclient.Client, timeout time.Duration) (*types.Receipt, error) { + timeoutCh := time.After(timeout) + ticker := time.NewTicker(100 * time.Millisecond) + defer ticker.Stop() + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + for { + receipt, err := client.TransactionReceipt(ctx, hash) + if receipt != nil && err == nil { + return receipt, nil + } else if err != nil && !errors.Is(err, ethereum.NotFound) { + return nil, err + } + + select { + case <-timeoutCh: + tip, err := client.BlockByNumber(context.Background(), nil) + if err != nil { + return nil, err + } + return nil, fmt.Errorf("receipt for transaction %s not found. tip block number is %d: %w", hash.Hex(), tip.NumberU64(), errTimeout) + case <-ticker.C: + } + } +} + +func WaitForBlock(number *big.Int, client *ethclient.Client, timeout time.Duration) (*types.Block, error) { + timeoutCh := time.After(timeout) + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + + headChan := make(chan *types.Header, 100) + headSub, err := client.SubscribeNewHead(ctx, headChan) + if err != nil { + return nil, err + } + defer headSub.Unsubscribe() + + for { + select { + case head := <-headChan: + if head.Number.Cmp(number) >= 0 { + return client.BlockByNumber(ctx, number) + } + case err := <-headSub.Err(): + return nil, fmt.Errorf("error in head subscription: %w", err) + case <-timeoutCh: + return nil, errTimeout + } + } +} diff --git a/op-e2e/geth.go b/op-e2e/geth.go index 357f78e6f..90e32a102 100644 --- a/op-e2e/geth.go +++ b/op-e2e/geth.go @@ -1,26 +1,19 @@ package op_e2e import ( - "context" "crypto/ecdsa" - "errors" "fmt" "math/big" - "time" - "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-service/clock" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth/catalyst" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/tracers" - "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/node" @@ -30,98 +23,6 @@ import ( _ "github.com/ethereum/go-ethereum/eth/tracers/native" ) -var ( - // errTimeout represents a timeout - errTimeout = errors.New("timeout") -) - -func waitForL1OriginOnL2(l1BlockNum uint64, client *ethclient.Client, timeout time.Duration) (*types.Block, error) { - timeoutCh := time.After(timeout) - ctx, cancel := context.WithTimeout(context.Background(), timeout) - defer cancel() - - headChan := make(chan *types.Header, 100) - headSub, err := client.SubscribeNewHead(ctx, headChan) - if err != nil { - return nil, err - } - defer headSub.Unsubscribe() - - for { - select { - case head := <-headChan: - block, err := client.BlockByNumber(ctx, head.Number) - if err != nil { - return nil, err - } - l1Info, err := derive.L1InfoDepositTxData(block.Transactions()[0].Data()) - if err != nil { - return nil, err - } - if l1Info.Number >= l1BlockNum { - return block, nil - } - - case err := <-headSub.Err(): - return nil, fmt.Errorf("error in head subscription: %w", err) - case <-timeoutCh: - return nil, errTimeout - } - } -} - -func waitForTransaction(hash common.Hash, client *ethclient.Client, timeout time.Duration) (*types.Receipt, error) { - timeoutCh := time.After(timeout) - ticker := time.NewTicker(100 * time.Millisecond) - defer ticker.Stop() - ctx, cancel := context.WithTimeout(context.Background(), timeout) - defer cancel() - for { - receipt, err := client.TransactionReceipt(ctx, hash) - if receipt != nil && err == nil { - return receipt, nil - } else if err != nil && !errors.Is(err, ethereum.NotFound) { - return nil, err - } - - select { - case <-timeoutCh: - tip, err := client.BlockByNumber(context.Background(), nil) - if err != nil { - return nil, err - } - return nil, fmt.Errorf("receipt for transaction %s not found. tip block number is %d: %w", hash.Hex(), tip.NumberU64(), errTimeout) - case <-ticker.C: - } - } -} - -func waitForBlock(number *big.Int, client *ethclient.Client, timeout time.Duration) (*types.Block, error) { - timeoutCh := time.After(timeout) - ctx, cancel := context.WithTimeout(context.Background(), timeout) - defer cancel() - - headChan := make(chan *types.Header, 100) - headSub, err := client.SubscribeNewHead(ctx, headChan) - if err != nil { - return nil, err - } - defer headSub.Unsubscribe() - - for { - select { - case head := <-headChan: - if head.Number.Cmp(number) >= 0 { - return client.BlockByNumber(ctx, number) - } - case err := <-headSub.Err(): - return nil, fmt.Errorf("error in head subscription: %w", err) - case <-timeoutCh: - return nil, errTimeout - } - } -} - func initL1Geth(cfg *SystemConfig, genesis *core.Genesis, c clock.Clock, opts ...GethOption) (*node.Node, *eth.Ethereum, error) { ethConfig := ðconfig.Config{ NetworkId: cfg.DeployConfig.L1ChainID, diff --git a/op-e2e/setup.go b/op-e2e/setup.go index dc055a5b6..083768f5f 100644 --- a/op-e2e/setup.go +++ b/op-e2e/setup.go @@ -14,6 +14,7 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-node/p2p/store" "github.com/ethereum-optimism/optimism/op-service/clock" ds "github.com/ipfs/go-datastore" @@ -505,7 +506,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste sys.Clients[name] = client } - _, err = waitForBlock(big.NewInt(2), l1Client, 6*time.Second*time.Duration(cfg.DeployConfig.L1BlockTime)) + _, err = geth.WaitForBlock(big.NewInt(2), l1Client, 6*time.Second*time.Duration(cfg.DeployConfig.L1BlockTime)) if err != nil { return nil, fmt.Errorf("waiting for blocks: %w", err) } diff --git a/op-e2e/system_fpp_test.go b/op-e2e/system_fpp_test.go index 8ac05f21d..406515b56 100644 --- a/op-e2e/system_fpp_test.go +++ b/op-e2e/system_fpp_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-node/client" "github.com/ethereum-optimism/optimism/op-node/sources" "github.com/ethereum-optimism/optimism/op-node/testlog" @@ -99,7 +100,7 @@ func testVerifyL2OutputRootEmptyBlock(t *testing.T, detached bool) { t.Log("Wait for sequencer to catch up with last submitted batch") l1HeadNum, err := l1Client.BlockNumber(ctx) require.NoError(t, err) - _, err = waitForL1OriginOnL2(l1HeadNum, l2Seq, 30*time.Second) + _, err = geth.WaitForL1OriginOnL2(l1HeadNum, l2Seq, 30*time.Second) require.NoError(t, err) // Get the current safe head now that the batcher is stopped diff --git a/op-e2e/system_test.go b/op-e2e/system_test.go index ae4255254..2fc7d156f 100644 --- a/op-e2e/system_test.go +++ b/op-e2e/system_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -87,7 +88,7 @@ func TestL2OutputSubmitter(t *testing.T) { // for that block and subsequently reorgs to match what the verifier derives when running the // reconcillation process. l2Verif := sys.Clients["verifier"] - _, err = waitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) + _, err = geth.WaitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) require.Nil(t, err) // Wait for batch submitter to update L2 output oracle. @@ -369,7 +370,7 @@ func TestMissingBatchE2E(t *testing.T) { }) // Wait until the block it was first included in shows up in the safe chain on the verifier - _, err = waitForBlock(receipt.BlockNumber, l2Verif, time.Duration((sys.RollupConfig.SeqWindowSize+4)*cfg.DeployConfig.L1BlockTime)*time.Second) + _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, time.Duration((sys.RollupConfig.SeqWindowSize+4)*cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for block on verifier") // Assert that the transaction is not found on the verifier @@ -722,7 +723,7 @@ func TestSystemP2PAltSync(t *testing.T) { l2Verif := ethclient.NewClient(rpc) // It may take a while to sync, but eventually we should see the sequenced data show up - receiptVerif, err := waitForTransaction(receiptSeq.TxHash, l2Verif, 100*time.Duration(sys.RollupConfig.BlockTime)*time.Second) + receiptVerif, err := geth.WaitForTransaction(receiptSeq.TxHash, l2Verif, 100*time.Duration(sys.RollupConfig.BlockTime)*time.Second) require.Nil(t, err, "Waiting for L2 tx on verifier") require.Equal(t, receiptSeq, receiptVerif) @@ -852,9 +853,9 @@ func TestL1InfoContract(t *testing.T) { endVerifBlockNumber := big.NewInt(4) endSeqBlockNumber := big.NewInt(6) - endVerifBlock, err := waitForBlock(endVerifBlockNumber, l2Verif, time.Minute) + endVerifBlock, err := geth.WaitForBlock(endVerifBlockNumber, l2Verif, time.Minute) require.Nil(t, err) - endSeqBlock, err := waitForBlock(endSeqBlockNumber, l2Seq, time.Minute) + endSeqBlock, err := geth.WaitForBlock(endSeqBlockNumber, l2Seq, time.Minute) require.Nil(t, err) seqL1Info, err := bindings.NewL1Block(cfg.L1InfoPredeployAddress, l2Seq) @@ -1251,7 +1252,7 @@ func TestStopStartBatcher(t *testing.T) { // wait until the block the tx was first included in shows up in the safe chain on the verifier safeBlockInclusionDuration := time.Duration(6*cfg.DeployConfig.L1BlockTime) * time.Second - _, err = waitForBlock(receipt.BlockNumber, l2Verif, safeBlockInclusionDuration) + _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, safeBlockInclusionDuration) require.Nil(t, err, "Waiting for block on verifier") // ensure the safe chain advances @@ -1288,7 +1289,7 @@ func TestStopStartBatcher(t *testing.T) { receipt = sendTx() // wait until the block the tx was first included in shows up in the safe chain on the verifier - _, err = waitForBlock(receipt.BlockNumber, l2Verif, safeBlockInclusionDuration) + _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, safeBlockInclusionDuration) require.Nil(t, err, "Waiting for block on verifier") // ensure that the safe chain advances after restarting the batcher @@ -1310,7 +1311,7 @@ func TestBatcherMultiTx(t *testing.T) { l1Client := sys.Clients["l1"] l2Seq := sys.Clients["sequencer"] - _, err = waitForBlock(big.NewInt(10), l2Seq, time.Duration(cfg.DeployConfig.L2BlockTime*15)*time.Second) + _, err = geth.WaitForBlock(big.NewInt(10), l2Seq, time.Duration(cfg.DeployConfig.L2BlockTime*15)*time.Second) require.Nil(t, err, "Waiting for L2 blocks") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) @@ -1327,7 +1328,7 @@ func TestBatcherMultiTx(t *testing.T) { // possible additional L1 blocks will be created before the batcher starts, // so we wait additional blocks. for i := int64(0); i < 10; i++ { - block, err := waitForBlock(big.NewInt(int64(l1Number)+i), l1Client, time.Duration(cfg.DeployConfig.L1BlockTime*5)*time.Second) + block, err := geth.WaitForBlock(big.NewInt(int64(l1Number)+i), l1Client, time.Duration(cfg.DeployConfig.L1BlockTime*5)*time.Second) require.Nil(t, err, "Waiting for l1 blocks") totalTxCount += len(block.Transactions()) diff --git a/op-e2e/system_tob_test.go b/op-e2e/system_tob_test.go index cf8d114eb..bb1cd9e6f 100644 --- a/op-e2e/system_tob_test.go +++ b/op-e2e/system_tob_test.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-node/testutils/fuzzerutils" "github.com/ethereum-optimism/optimism/op-node/withdrawals" @@ -70,11 +71,11 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) { cancel() require.Nil(t, err, "sending overhead update tx") - receipt, err := waitForTransaction(tx.Hash(), l1Client, txTimeoutDuration) + receipt, err := geth.WaitForTransaction(tx.Hash(), l1Client, txTimeoutDuration) require.Nil(t, err, "waiting for sysconfig set gas config update tx") require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed") - _, err = waitForL1OriginOnL2(receipt.BlockNumber.Uint64(), l2Seq, txTimeoutDuration) + _, err = geth.WaitForL1OriginOnL2(receipt.BlockNumber.Uint64(), l2Seq, txTimeoutDuration) require.NoError(t, err, "waiting for L2 block to include the sysconfig update") gpoOverhead, err := gpoContract.Overhead(&bind.CallOpts{}) @@ -97,11 +98,11 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) { cancel() require.Nil(t, err, "sending overhead update tx") - receipt, err = waitForTransaction(tx.Hash(), l1Client, txTimeoutDuration) + receipt, err = geth.WaitForTransaction(tx.Hash(), l1Client, txTimeoutDuration) require.Nil(t, err, "waiting for sysconfig set gas config update tx") require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed") - _, err = waitForL1OriginOnL2(receipt.BlockNumber.Uint64(), l2Seq, txTimeoutDuration) + _, err = geth.WaitForL1OriginOnL2(receipt.BlockNumber.Uint64(), l2Seq, txTimeoutDuration) require.NoError(t, err, "waiting for L2 block to include the sysconfig update") gpoOverhead, err = gpoContract.Overhead(&bind.CallOpts{}) @@ -504,7 +505,7 @@ func TestMixedWithdrawalValidity(t *testing.T) { require.Nil(t, err, "sending initiate withdraw tx") t.Logf("Waiting for tx %s to be in sequencer", tx.Hash().Hex()) - receiptSeq, err := waitForTransaction(tx.Hash(), l2Seq, txTimeoutDuration) + receiptSeq, err := geth.WaitForTransaction(tx.Hash(), l2Seq, txTimeoutDuration) require.Nil(t, err, "withdrawal initiated on L2 sequencer") require.Equal(t, receiptSeq.Status, types.ReceiptStatusSuccessful, "transaction failed") @@ -513,7 +514,7 @@ func TestMixedWithdrawalValidity(t *testing.T) { t.Logf("Waiting for tx %s to be in verifier. Verifier tip is %s:%d. Included in sequencer in block %s:%d", tx.Hash().Hex(), verifierTip.Hash().Hex(), verifierTip.NumberU64(), receiptSeq.BlockHash.Hex(), receiptSeq.BlockNumber) // Wait for the transaction to appear in L2 verifier - receipt, err := waitForTransaction(tx.Hash(), l2Verif, txTimeoutDuration) + receipt, err := geth.WaitForTransaction(tx.Hash(), l2Verif, txTimeoutDuration) require.Nilf(t, err, "withdrawal tx %s not found in verifier. included in block %s:%d", tx.Hash().Hex(), receiptSeq.BlockHash.Hex(), receiptSeq.BlockNumber) require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed") @@ -638,7 +639,7 @@ func TestMixedWithdrawalValidity(t *testing.T) { } else { require.NoError(t, err) - receipt, err = waitForTransaction(tx.Hash(), l1Client, txTimeoutDuration) + receipt, err = geth.WaitForTransaction(tx.Hash(), l1Client, txTimeoutDuration) require.Nil(t, err, "finalize withdrawal") require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) @@ -656,7 +657,7 @@ func TestMixedWithdrawalValidity(t *testing.T) { transactor.ExpectedL1Nonce++ // Ensure that our withdrawal was proved successfully - proveReceipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + proveReceipt, err := geth.WaitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "prove withdrawal") require.Equal(t, types.ReceiptStatusSuccessful, proveReceipt.Status) diff --git a/op-e2e/tx_helper.go b/op-e2e/tx_helper.go index 423272540..eb07e8070 100644 --- a/op-e2e/tx_helper.go +++ b/op-e2e/tx_helper.go @@ -8,6 +8,7 @@ import ( "time" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -39,14 +40,14 @@ func SendDepositTx(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, l require.Nil(t, err, "with deposit tx") // Wait for transaction on L1 - l1Receipt, err := waitForTransaction(tx.Hash(), l1Client, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + l1Receipt, err := geth.WaitForTransaction(tx.Hash(), l1Client, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "Waiting for deposit tx on L1") // Wait for transaction to be included on L2 reconstructedDep, err := derive.UnmarshalDepositLogEvent(l1Receipt.Logs[0]) require.NoError(t, err, "Could not reconstruct L2 Deposit") tx = types.NewTx(reconstructedDep) - l2Receipt, err := waitForTransaction(tx.Hash(), l2Client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) + l2Receipt, err := geth.WaitForTransaction(tx.Hash(), l2Client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) require.NoError(t, err) require.Equal(t, l2Opts.ExpectedStatus, l2Receipt.Status, "l2 transaction status") return l2Receipt @@ -95,13 +96,13 @@ func SendL2Tx(t *testing.T, cfg SystemConfig, l2Client *ethclient.Client, privKe err := l2Client.SendTransaction(ctx, tx) require.NoError(t, err, "Sending L2 tx") - receipt, err := waitForTransaction(tx.Hash(), l2Client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) + receipt, err := geth.WaitForTransaction(tx.Hash(), l2Client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) require.NoError(t, err, "Waiting for L2 tx") require.Equal(t, opts.ExpectedStatus, receipt.Status, "TX should have expected status") for i, client := range opts.VerifyClients { t.Logf("Waiting for tx %v on verification client %d", tx.Hash(), i) - receiptVerif, err := waitForTransaction(tx.Hash(), client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) + receiptVerif, err := geth.WaitForTransaction(tx.Hash(), client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) require.NoErrorf(t, err, "Waiting for L2 tx on verification client %d", i) require.Equalf(t, receipt, receiptVerif, "Receipts should be the same on sequencer and verification client %d", i) } diff --git a/op-e2e/withdrawal_helper.go b/op-e2e/withdrawal_helper.go index d521d42eb..90617db1a 100644 --- a/op-e2e/withdrawal_helper.go +++ b/op-e2e/withdrawal_helper.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/config" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-node/withdrawals" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -36,13 +37,13 @@ func SendWithdrawal(t *testing.T, cfg SystemConfig, l2Client *ethclient.Client, tx, err := l2withdrawer.InitiateWithdrawal(l2opts, l2opts.From, big.NewInt(int64(opts.Gas)), opts.Data) require.Nil(t, err, "sending initiate withdraw tx") - receipt, err := waitForTransaction(tx.Hash(), l2Client, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + receipt, err := geth.WaitForTransaction(tx.Hash(), l2Client, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "withdrawal initiated on L2 sequencer") require.Equal(t, opts.ExpectedStatus, receipt.Status, "transaction had incorrect status") for i, client := range opts.VerifyClients { t.Logf("Waiting for tx %v on verification client %d", tx.Hash(), i) - receiptVerif, err := waitForTransaction(tx.Hash(), client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) + receiptVerif, err := geth.WaitForTransaction(tx.Hash(), client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) require.Nilf(t, err, "Waiting for L2 tx on verification client %d", i) require.Equalf(t, receipt, receiptVerif, "Receipts should be the same on sequencer and verification client %d", i) } @@ -134,7 +135,7 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, require.Nil(t, err) // Ensure that our withdrawal was proved successfully - proveReceipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + proveReceipt, err := geth.WaitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "prove withdrawal") require.Equal(t, types.ReceiptStatusSuccessful, proveReceipt.Status) return params, proveReceipt @@ -167,7 +168,7 @@ func FinalizeWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Clie require.Nil(t, err) // Ensure that our withdrawal was finalized successfully - finalizeReceipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + finalizeReceipt, err := geth.WaitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.Nil(t, err, "finalize withdrawal") require.Equal(t, types.ReceiptStatusSuccessful, finalizeReceipt.Status) return finalizeReceipt From aeeb19270b870b49fe6e1d8868bf3e875adb5314 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Tue, 5 Sep 2023 13:36:16 +1000 Subject: [PATCH 29/59] op-e2e: Move geth init utils to e2eutils --- op-e2e/{ => e2eutils/geth}/fakepos.go | 2 +- op-e2e/{ => e2eutils/geth}/geth.go | 42 ++++++--------------------- op-e2e/l2_gossip_test.go | 2 +- op-e2e/op_geth.go | 3 +- op-e2e/setup.go | 8 ++--- op-e2e/system_test.go | 6 ++-- 6 files changed, 20 insertions(+), 43 deletions(-) rename op-e2e/{ => e2eutils/geth}/fakepos.go (99%) rename op-e2e/{ => e2eutils/geth}/geth.go (76%) diff --git a/op-e2e/fakepos.go b/op-e2e/e2eutils/geth/fakepos.go similarity index 99% rename from op-e2e/fakepos.go rename to op-e2e/e2eutils/geth/fakepos.go index 08977c013..081a5b838 100644 --- a/op-e2e/fakepos.go +++ b/op-e2e/e2eutils/geth/fakepos.go @@ -1,4 +1,4 @@ -package op_e2e +package geth import ( "time" diff --git a/op-e2e/geth.go b/op-e2e/e2eutils/geth/geth.go similarity index 76% rename from op-e2e/geth.go rename to op-e2e/e2eutils/geth/geth.go index 90e32a102..ad02eac36 100644 --- a/op-e2e/geth.go +++ b/op-e2e/e2eutils/geth/geth.go @@ -1,12 +1,10 @@ -package op_e2e +package geth import ( - "crypto/ecdsa" "fmt" "math/big" "github.com/ethereum-optimism/optimism/op-service/clock" - "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -23,9 +21,9 @@ import ( _ "github.com/ethereum/go-ethereum/eth/tracers/native" ) -func initL1Geth(cfg *SystemConfig, genesis *core.Genesis, c clock.Clock, opts ...GethOption) (*node.Node, *eth.Ethereum, error) { +func InitL1(chainID uint64, blockTime uint64, genesis *core.Genesis, c clock.Clock, opts ...GethOption) (*node.Node, *eth.Ethereum, error) { ethConfig := ðconfig.Config{ - NetworkId: cfg.DeployConfig.L1ChainID, + NetworkId: chainID, Genesis: genesis, } nodeConfig := &node.Config{ @@ -38,7 +36,7 @@ func initL1Geth(cfg *SystemConfig, genesis *core.Genesis, c clock.Clock, opts .. HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"}, } - l1Node, l1Eth, err := createGethNode(false, nodeConfig, ethConfig, []*ecdsa.PrivateKey{cfg.Secrets.CliqueSigner}, opts...) + l1Node, l1Eth, err := createGethNode(false, nodeConfig, ethConfig, opts...) if err != nil { return nil, nil, err } @@ -50,7 +48,7 @@ func initL1Geth(cfg *SystemConfig, genesis *core.Genesis, c clock.Clock, opts .. clock: c, eth: l1Eth, log: log.Root(), // geth logger is global anyway. Would be nice to replace with a local logger though. - blockTime: cfg.DeployConfig.L1BlockTime, + blockTime: blockTime, // for testing purposes we make it really fast, otherwise we don't see it finalize in short tests finalizedDistance: 8, safeDistance: 4, @@ -77,8 +75,8 @@ func defaultNodeConfig(name string, jwtPath string) *node.Config { type GethOption func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error -// init a geth node. -func initL2Geth(name string, l2ChainID *big.Int, genesis *core.Genesis, jwtPath string, opts ...GethOption) (*node.Node, *eth.Ethereum, error) { +// InitL2 inits a L2 geth node. +func InitL2(name string, l2ChainID *big.Int, genesis *core.Genesis, jwtPath string, opts ...GethOption) (*node.Node, *eth.Ethereum, error) { ethConfig := ðconfig.Config{ NetworkId: l2ChainID.Uint64(), Genesis: genesis, @@ -93,14 +91,14 @@ func initL2Geth(name string, l2ChainID *big.Int, genesis *core.Genesis, jwtPath }, } nodeConfig := defaultNodeConfig(fmt.Sprintf("l2-geth-%v", name), jwtPath) - return createGethNode(true, nodeConfig, ethConfig, nil, opts...) + return createGethNode(true, nodeConfig, ethConfig, opts...) } // createGethNode creates an in-memory geth node based on the configuration. // The private keys are added to the keystore and are unlocked. // If the node is l2, catalyst is enabled. // The node should be started and then closed when done. -func createGethNode(l2 bool, nodeCfg *node.Config, ethCfg *ethconfig.Config, privateKeys []*ecdsa.PrivateKey, opts ...GethOption) (*node.Node, *eth.Ethereum, error) { +func createGethNode(l2 bool, nodeCfg *node.Config, ethCfg *ethconfig.Config, opts ...GethOption) (*node.Node, *eth.Ethereum, error) { for i, opt := range opts { if err := opt(ethCfg, nodeCfg); err != nil { return nil, nil, fmt.Errorf("failed to apply geth option %d: %w", i, err) @@ -113,28 +111,6 @@ func createGethNode(l2 bool, nodeCfg *node.Config, ethCfg *ethconfig.Config, pri return nil, nil, err } - if !l2 { - keydir := n.KeyStoreDir() - scryptN := 2 - scryptP := 1 - n.AccountManager().AddBackend(keystore.NewKeyStore(keydir, scryptN, scryptP)) - ks := n.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) - - password := "foobar" - for _, pk := range privateKeys { - act, err := ks.ImportECDSA(pk, password) - if err != nil { - n.Close() - return nil, nil, err - } - err = ks.Unlock(act, password) - if err != nil { - n.Close() - return nil, nil, err - } - } - } - backend, err := eth.New(n, ethCfg) if err != nil { n.Close() diff --git a/op-e2e/l2_gossip_test.go b/op-e2e/l2_gossip_test.go index ff7f403e1..530247401 100644 --- a/op-e2e/l2_gossip_test.go +++ b/op-e2e/l2_gossip_test.go @@ -11,7 +11,7 @@ import ( func TestTxGossip(t *testing.T) { InitParallel(t) cfg := DefaultSystemConfig(t) - gethOpts := []GethOption{ + gethOpts := []geth.GethOption{ geth.WithP2P(), } cfg.GethOptions["sequencer"] = gethOpts diff --git a/op-e2e/op_geth.go b/op-e2e/op_geth.go index fe975ef0d..2e78d087a 100644 --- a/op-e2e/op_geth.go +++ b/op-e2e/op_geth.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-e2e/config" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-node/client" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" @@ -72,7 +73,7 @@ func NewOpGeth(t *testing.T, ctx context.Context, cfg *SystemConfig) (*OpGeth, e SystemConfig: e2eutils.SystemConfigFromDeployConfig(cfg.DeployConfig), } - node, _, err := initL2Geth("l2", big.NewInt(int64(cfg.DeployConfig.L2ChainID)), l2Genesis, cfg.JWTFilePath) + node, _, err := geth.InitL2("l2", big.NewInt(int64(cfg.DeployConfig.L2ChainID)), l2Genesis, cfg.JWTFilePath) require.Nil(t, err) require.Nil(t, node.Start()) diff --git a/op-e2e/setup.go b/op-e2e/setup.go index 083768f5f..a61259656 100644 --- a/op-e2e/setup.go +++ b/op-e2e/setup.go @@ -139,7 +139,7 @@ func DefaultSystemConfig(t *testing.T) SystemConfig { "batcher": testlog.Logger(t, log.LvlInfo).New("role", "batcher"), "proposer": testlog.Logger(t, log.LvlCrit).New("role", "proposer"), }, - GethOptions: map[string][]GethOption{}, + GethOptions: map[string][]geth.GethOption{}, P2PTopology: nil, // no P2P connectivity by default NonFinalizedProposals: false, ExternalL2Shim: config.ExternalL2Shim, @@ -174,7 +174,7 @@ type SystemConfig struct { Premine map[common.Address]*big.Int Nodes map[string]*rollupNode.Config // Per node config. Don't use populate rollup.Config Loggers map[string]log.Logger - GethOptions map[string][]GethOption + GethOptions map[string][]geth.GethOption ProposerLogger log.Logger BatcherLogger log.Logger @@ -425,7 +425,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste sys.RollupConfig = &defaultConfig // Initialize nodes - l1Node, l1Backend, err := initL1Geth(&cfg, l1Genesis, c, cfg.GethOptions["l1"]...) + l1Node, l1Backend, err := geth.InitL1(cfg.DeployConfig.L1ChainID, cfg.DeployConfig.L1BlockTime, l1Genesis, c, cfg.GethOptions["l1"]...) if err != nil { return nil, err } @@ -442,7 +442,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste for name := range cfg.Nodes { var ethClient EthInstance if cfg.ExternalL2Shim == "" { - node, backend, err := initL2Geth(name, big.NewInt(int64(cfg.DeployConfig.L2ChainID)), l2Genesis, cfg.JWTFilePath, cfg.GethOptions[name]...) + node, backend, err := geth.InitL2(name, big.NewInt(int64(cfg.DeployConfig.L2ChainID)), l2Genesis, cfg.JWTFilePath, cfg.GethOptions[name]...) if err != nil { return nil, err } diff --git a/op-e2e/system_test.go b/op-e2e/system_test.go index 2fc7d156f..a9f1dce0f 100644 --- a/op-e2e/system_test.go +++ b/op-e2e/system_test.go @@ -260,14 +260,14 @@ func TestPendingGasLimit(t *testing.T) { // configure the L2 gas limit to be high, and the pending gas limits to be lower for resource saving. cfg.DeployConfig.L2GenesisBlockGasLimit = 30_000_000 - cfg.GethOptions["sequencer"] = []GethOption{ + cfg.GethOptions["sequencer"] = []geth.GethOption{ func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { ethCfg.Miner.GasCeil = 10_000_000 ethCfg.Miner.RollupComputePendingBlock = true return nil }, } - cfg.GethOptions["verifier"] = []GethOption{ + cfg.GethOptions["verifier"] = []geth.GethOption{ func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { ethCfg.Miner.GasCeil = 9_000_000 ethCfg.Miner.RollupComputePendingBlock = true @@ -701,7 +701,7 @@ func TestSystemP2PAltSync(t *testing.T) { }, } configureL1(syncNodeCfg, sys.EthInstances["l1"]) - syncerL2Engine, _, err := initL2Geth("syncer", big.NewInt(int64(cfg.DeployConfig.L2ChainID)), sys.L2GenesisCfg, cfg.JWTFilePath) + syncerL2Engine, _, err := geth.InitL2("syncer", big.NewInt(int64(cfg.DeployConfig.L2ChainID)), sys.L2GenesisCfg, cfg.JWTFilePath) require.NoError(t, err) require.NoError(t, syncerL2Engine.Start()) From 932a9bc97c7558f333dbdb278884ded21a1fa5dd Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Mon, 4 Sep 2023 15:38:06 +1000 Subject: [PATCH 30/59] Add initial documentation for fault proof alpha. --- docs/README.md | 1 + docs/fault-proof-alpha/README.md | 16 ++++ docs/fault-proof-alpha/cannon.md | 92 +++++++++++++++++++ docs/fault-proof-alpha/deployments.md | 24 +++++ docs/fault-proof-alpha/manual.md | 110 +++++++++++++++++++++++ docs/fault-proof-alpha/run-challenger.md | 64 +++++++++++++ 6 files changed, 307 insertions(+) create mode 100644 docs/fault-proof-alpha/README.md create mode 100644 docs/fault-proof-alpha/cannon.md create mode 100644 docs/fault-proof-alpha/deployments.md create mode 100644 docs/fault-proof-alpha/manual.md create mode 100644 docs/fault-proof-alpha/run-challenger.md diff --git a/docs/README.md b/docs/README.md index cabb2506b..da82e0a7f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,3 +6,4 @@ The directory layout is divided into the following sub-directories. - [`postmortems/`](./postmortems/): Timestamped post-mortem documents. - [`security-reviews`](./security-reviews/): Audit summaries and other security review documents. +- [`fault-proof-alpha`](./fault-proof-alpha): Information on the alpha version of the fault proof system. diff --git a/docs/fault-proof-alpha/README.md b/docs/fault-proof-alpha/README.md new file mode 100644 index 000000000..0655593de --- /dev/null +++ b/docs/fault-proof-alpha/README.md @@ -0,0 +1,16 @@ +## Fault Proofs Alpha + +The fault proof alpha is a pre-release version of the OP Stack fault proof system. +This documentation provides an overview of the system and instructions on how to help +test the fault proof system. + +The overall design of this system along with the APIs and interfaces it exposes are not +finalized and may change without notice. + +### Contents + + * Overview + * Deployment Details + * [Manual Usage](./manual.md) + * [Creating Traces with Cannon](./cannon.md) + * [Automation with `op-challenger`](./run-challenger.md) diff --git a/docs/fault-proof-alpha/cannon.md b/docs/fault-proof-alpha/cannon.md new file mode 100644 index 000000000..7013ca9de --- /dev/null +++ b/docs/fault-proof-alpha/cannon.md @@ -0,0 +1,92 @@ +## Generate Traces with `cannon` and `op-program` + +Normally, `op-challenger` handles creating the required traces as part of responding to games. However, for manual +testing it may be useful to manually generate the trace. This can be done by running `cannon` directly. + +### Prerequisites + +- The cannon pre-state downloaded from [Goerli deployment](./deployments.md#goerli). +- A Goerli L1 node. + - An archive node is not required. + - Public RPC providers can be used, however a significant number of requests will need to be made which may exceed + rate limits for free plans. +- An OP-Goerli L2 archive node with `debug` APIs enabled. + - An archive node is required to ensure world-state pre-images remain available. + - Public RPC providers are generally not usable as they don’t support the `debug_dbGet` RPC method. + +### Compilation + +To compile the required programs, in the top level of the monorepo run: + +```bash +make cannon-prestate +``` + +This will compile the `cannon` executable to `cannon/bin/cannon` as well as the `op-program` executable used to fetch +pre-image data to `op-program/bin/op-program`. + +### Run Cannon + +To run cannon to generate a proof use: + +```bash +mkdir -p temp/cannon/proofs temp/cannon/snapshots temp/cannon/preimages + +./cannon/bin/cannon run \ + --pprof.cpu \ + --info-at '%10000000' \ + --proof-at '=' \ + --stop-at '=' \ + --proof-fmt 'temp/cannon/proofs/%d.json' \ + --snapshot-at '%1000000000' \ + --snapshot-fmt 'temp/cannon/snapshots/%d.json.gz' \ + --input \ + --output temp/cannon/stop-state.json \ + -- \ + ./op-program/bin/op-program \ + --network goerli \ + --l1 \ + --l2 \ + --l1.head \ + --l2.claim \ + --l2.head \ + --l2.blocknumber \ + --datadir temp/cannon/preimages \ + --log.format terminal \ + --server +``` + +The placeholders are: + +- `` the index in the trace to generate a proof for +- `` the index to stop execution at. Typically this is one instruction after `` to stop as soon + as the required proof has been generated. +- `` the prestate.json downloaded above. Note that this needs to precisely match the prestate used on-chain so + must be the downloaded version and not a version built locally. +- `` the Goerli L1 JSON RPC endpoint +- `` the OP-Goerli L2 archive node JSON RPC endpoint +- `` the hash of the L1 head block used for the dispute game +- `` the output root immediately prior to the disputed root in the L2 output oracle +- `` the hash of the L2 block that ``is from +- `` the block number that `` is from + +The generated proof will be stored in the `temp/cannon/proofs/` directory. The hash to use as the claim value is +the `post` field of the generated proof which provides the hash of the cannon state witness after execution of the step. + +Since cannon can be very slow to execute, the above command uses the `--snapshot-at` option to generate a snapshot of +the cannon state every 1000000000 instructions. Once generated, these snapshots can be used as the `--input` to begin +execution at that step rather than from the very beginning. Generated snapshots are stored in +the `temp/cannon/snapshots` directory. + +See `./cannon/bin/cannon --help` for further information on the options available. + +### Trace Extension + +Fault dispute games always use a trace with a fixed length of `2 ^ MAX_GAME_DEPTH`. The trace generated by `cannon` +stops when the client program exits, so this trace must be extended by repeating the hash of the final state in the +actual trace for all remaining steps. Cannon does not perform this trace extension automatically. + +If cannon stops execution before the trace index you requested a proof at, it simply will not generate a proof. When it +stops executing, it will write its final state to `temp/cannon/stop-state.json` (controlled by the `--output` option). +The `step` field of this state contains the last step cannon executed. Once the final step is known, rerun cannon to +generate the proof at that final step and use the `post` hash as the claim value for all later trace indices. diff --git a/docs/fault-proof-alpha/deployments.md b/docs/fault-proof-alpha/deployments.md new file mode 100644 index 000000000..3a49f7381 --- /dev/null +++ b/docs/fault-proof-alpha/deployments.md @@ -0,0 +1,24 @@ +## Fault Proof Alpha Deployment Information + +### Goerli + +Information on the fault proofs alpha deployment to Goerli is not yet available. + +### Local Devnet + +The local devnet includes a deployment of the fault proof alpha. To start the devnet, in the top level of this repo, +run: + +```bash +make devnet-up +``` + +| Input | Value | +|----------------------|-------------------------------------------------------------| +| Dispute Game Factory | Run `jq -r .DisputeGameFactoryProxy .devnet/addresses.json` | +| Absolute Prestate | `op-program/bin/prestate.json` | +| Max Depth | 30 | +| Max Game Duration | 1200 (20 minutes) | + +See the [op-challenger README](../../op-challenger#running-with-cannon-on-local-devnet) for information on +running `op-challenger` against the local devnet. diff --git a/docs/fault-proof-alpha/manual.md b/docs/fault-proof-alpha/manual.md new file mode 100644 index 000000000..1b7afd4aa --- /dev/null +++ b/docs/fault-proof-alpha/manual.md @@ -0,0 +1,110 @@ +## Manual Fault Proof Interactions + +## Creating a Game + +The process of disputing an output root starts by creating a new dispute game. There are conceptually three key inputs +required for a dispute game: + +- The output root being disputed +- The agreed output root the derivation process will start from +- The L1 head block that defines the canonical L1 chain containing all required batch data to perform the derivation + +The creator of the game selects the output root to dispute. It is identified by its L2 block number which can be used to +look up the full details in the L2 output oracle. + +The agreed output root is defined as the output root immediately prior to the disputed output root in the L2 output +oracle. Therefore, a dispute game should only be created for the first invalid output root. If it is successfully +disputed, all output roots after it would be considered invalid by inference. + +The L1 head block can be any L1 block where the disputed output root is present in the L2 output oracle. Proposers +should therefore ensure that all batch data has been submitted to L1 before submitting a proposal. The L1 head block is +recorded in the `BlockOracle` and then referenced by its block number. + +Creating a game requires two separate transactions. First the L1 head block is recorded in the `BlockOracle` by calling +its `checkpoint` function. This record the parent of the block the transaction is included in. The `BlockOracle` emits a +log `Checkpoint(blockNumber, blockHash, childTimestamp)`. + +Now the L1 head, along with the information on the output roots from the L2 output oracle can be used to execute cannon +and determine the root claim to use when creating the game. In simple cases, where the claim is expected to be +incorrect, an arbitrary hash can be used for claim values. For more advanced cases [cannon can be used](./cannon.md) to +generate a trace, including the claim values to use at specific steps. Note that it is not valid to create a game that +disputes an output root, using the final hash from a trace that confirms the output root is valid. To dispute an output +root successfully, the trace must resolve that the disputed output root is invalid. + +The game can then be created by calling the `create` method on the `DisputeGameFactory` contract. This requires three +parameters: + +- `gameType` - a `uint8` representing the type of game to create. For fault dispute games using cannon and op-program + traces, the game type is 0. +- `rootClaim` - a `bytes32` hash of the final state from the trace. +- `extraData` - arbitrary bytes which are used as the initial inputs for the game. For fault dispute games using cannon + and op-program traces, this is the abi encoding of `(uint256(l2_block_number), uint256(l1_checkpoint))`. + - `l2_block_number` is the L2 block number from the output root being disputed + - `l1_checkpoint` is the L1 block number recorded by the `BlockOracle` checkpoint + +This emits a log event `DisputeGameCreated(gameAddress, gameType, rootClaim)` where `gameAddress` is the address of the +newly created dispute game. + +A simple helper script, [create_game.sh](../../op-challenger#create_gamesh) has been created to easily create a new +dispute game and also provides an example of using `cast` to manually create a game. + +## Performing Moves + +The dispute game progresses by actors by countering existing claims via either the `attack` or `defend` methods in +the `FaultDisputeGame` contract. Note that only `attack` can be used to counter the root claim. In both cases, there are +two inputs required: + +- `parentIndex` - the index in the claims array of the parent claim that is being countered +- `claim` - a `bytes32` hash of the state at the trace index corresponding to the new claim’s position. + +A simple helper script, [move.sh](../../op-challenger#movesh), has been created to easily perform moves and also +provides an example of using `cast` to manually call `attack` and `defend`. + +## Performing Steps + +Attack and defend can only be used until the maximum depth of the game is reached. To counter claims at the maximum +depth, a step must be performed instead. Calling the `step` method in the `FaultDisputeGame` contract counters a claim +at the maximum depth by running a single step of the cannon VM on chain. The `step` method will revert unless the cannon +execution confirms the claim being countered is invalid. + +The inputs for step are: + +- `claimIndex` - the index in the claims array of the claim that is being countered +- `isAttack` - Similar to regular moves, steps can either be attacking or defending +- `stateData` - the full cannon state witness to use as the starting state for execution +- `proof` - the additional proof data for the state witness required by cannon to perform the step + +When a step is attacking, the caller is making the claim that the claim at `claimIndex` is incorrect, and the claim for +the previous trace index (made at a previous level in the game) was correct. The `stateData` must be the pre-image for +the agreed correct hash at the previous trace index. The call to `step` will revert if the post-state from cannon +matches the claim at `claimIndex` since the on-chain execution has proven the claim correct and it should not be +countered. + +When a step is defending, the caller is making the claim that the claim at `claimIndex` is correct, and the claim for +the next trac index (made at a previous level in the game) is incorrect. The `stateData` must be the pre-image for the +hash in the claim at `claimIndex`. + +The `step` function will revert with `ValidStep()` if the cannon execution proves that the claim attempting to be +countered is correct. As a result, claims at the maximum game depth can only be countered by a valid execution of the +single instruction in cannon running on-chain. + +### Populating the Pre-image Oracle + +When the instruction to be executed as part of a `step` call reads from some pre-image data, that data must be loaded +into the pre-image oracle prior to calling `step`. +For [local pre-image keys](../../specs/fault-proof.md#type-1-local-key), the pre-image must be populated via +the `FaultDisputeGame` contract by calling the `addLocalData` function. +For [global keccak256 keys](../../specs/fault-proof.md#type-2-global-keccak256-key), the data should be added directly +to the pre-image oracle contract. + +## Resolving a Game + +The final action required for a game is to resolve it by calling the `resolve` method in the `FaultDisputeGame` +contract. This can only be done once the clock of the left-most uncontested claim’s parent has expired. A game can only +be resolved once. + +There are no inputs required for the `resolve` method. When successful, a log event is emitted with the game’s final +status. + +A helper script, [resolve.sh](../../op-challenger#resolvesh), has been created to easily resolve a game and also +provides an example of using `cast` to manually call `resolve` and understand the result. diff --git a/docs/fault-proof-alpha/run-challenger.md b/docs/fault-proof-alpha/run-challenger.md new file mode 100644 index 000000000..5e23c58cc --- /dev/null +++ b/docs/fault-proof-alpha/run-challenger.md @@ -0,0 +1,64 @@ +## Running op-challenger + +`op-challenger` is a program that implements the honest actor algorithm to automatically “play” the dispute games. + +### Prerequisites + +- The cannon pre-state downloaded from [Goerli deployment](./deployments.md#goerli). +- An account on the Goerli testnet with funds available. The amount of GöETH required depends on the number of claims + the challenger needs to post, but 0.01 ETH should be plenty to start. +- A Goerli L1 node. + - An archive node is not required. + - Public RPC providers can be used, however a significant number of requests will need to be made which may exceed + rate limits for free plans. +- An OP-Goerli L2 archive node with `debug` APIs enabled. + - An archive node is required to ensure world-state pre-images remain available. + - Public RPC providers are generally not usable as they don’t support the `debug_dbGet` RPC method. +- Approximately 3.5Gb of disk space for each game being played. + +### Starting op-challenger + +In the top level of the monorepo, replace the placeholders and then run: + +```bash +# Build the required components +make op-challenger op-program cannon + +# Run op-challenger +./op-challenger/bin/op-challenger \ + --trace-type cannon \ + --l1-eth-rpc \ + --game-factory-address \ + --agree-with-proposed-output=true \ + --datadir temp/challenger-goerli \ + --cannon-network goerli \ + --cannon-bin ./cannon/bin/cannon \ + --cannon-server ./op-program/bin/op-program \ + --cannon-prestate \ + --cannon-l2 \ + --private-key +``` + +The placeholders are: + +- `` the Goerli L1 JSON RPC endpoint +- `` the address of the dispute game factory contract (see + the [Goerli deployment details](./deployments.md#goerli)) +- `` the prestate.json downloaded above. Note that this needs to precisely match the prestate used on-chain so + must be the downloaded version and not a version built locally (see the [Goerli deployment details](./deployments.md#goerli)) +- `` the OP-Goerli L2 archive node JSON RPC endpoint +- `` the private key for a funded Goerli account. For other ways to specify the account to use + see `./op-challenger/bin/op-challenger --help` + +### Restricting Games to Play + +By default `op-challenger` will generate traces and respond to any game created by the dispute game factory contract. On +a public testnet like Goerli, that could be a large number of games, requiring significant CPU and disk resources. To +avoid this, `op-challenger` supports specifying an allowlist of games for it to respond to with the `--game-allowlist` +option. + +```bash +./op-challenger/bin/op-challenger \ + ... \ + --game-allowlist ... +``` From 702eb6ba35d6973a91be97cbde054b0877edd910 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Wed, 6 Sep 2023 11:33:21 +1000 Subject: [PATCH 31/59] Update FPA docs based on review feedback. --- docs/fault-proof-alpha/README.md | 2 +- docs/fault-proof-alpha/manual.md | 49 ++++++++++++------------ docs/fault-proof-alpha/run-challenger.md | 23 +++++------ 3 files changed, 38 insertions(+), 36 deletions(-) diff --git a/docs/fault-proof-alpha/README.md b/docs/fault-proof-alpha/README.md index 0655593de..e5708c5f1 100644 --- a/docs/fault-proof-alpha/README.md +++ b/docs/fault-proof-alpha/README.md @@ -10,7 +10,7 @@ finalized and may change without notice. ### Contents * Overview - * Deployment Details + * [Deployment Details](./deployments.md) * [Manual Usage](./manual.md) * [Creating Traces with Cannon](./cannon.md) * [Automation with `op-challenger`](./run-challenger.md) diff --git a/docs/fault-proof-alpha/manual.md b/docs/fault-proof-alpha/manual.md index 1b7afd4aa..bb59ae712 100644 --- a/docs/fault-proof-alpha/manual.md +++ b/docs/fault-proof-alpha/manual.md @@ -14,22 +14,22 @@ look up the full details in the L2 output oracle. The agreed output root is defined as the output root immediately prior to the disputed output root in the L2 output oracle. Therefore, a dispute game should only be created for the first invalid output root. If it is successfully -disputed, all output roots after it would be considered invalid by inference. +disputed, all output roots after it are considered invalid by inference. The L1 head block can be any L1 block where the disputed output root is present in the L2 output oracle. Proposers should therefore ensure that all batch data has been submitted to L1 before submitting a proposal. The L1 head block is recorded in the `BlockOracle` and then referenced by its block number. Creating a game requires two separate transactions. First the L1 head block is recorded in the `BlockOracle` by calling -its `checkpoint` function. This record the parent of the block the transaction is included in. The `BlockOracle` emits a -log `Checkpoint(blockNumber, blockHash, childTimestamp)`. +its `checkpoint` function. This records the parent of the block the transaction is included in. The `BlockOracle` emits +a log `Checkpoint(blockNumber, blockHash, childTimestamp)`. -Now the L1 head, along with the information on the output roots from the L2 output oracle can be used to execute cannon -and determine the root claim to use when creating the game. In simple cases, where the claim is expected to be -incorrect, an arbitrary hash can be used for claim values. For more advanced cases [cannon can be used](./cannon.md) to -generate a trace, including the claim values to use at specific steps. Note that it is not valid to create a game that -disputes an output root, using the final hash from a trace that confirms the output root is valid. To dispute an output -root successfully, the trace must resolve that the disputed output root is invalid. +Now, using the L1 head along with output root info available in the L2 output oracle, cannon can be executed to +determine the root claim to use when creating the game. In simple cases, where the claim is expected to be incorrect, an +arbitrary hash can be used for claim values. For more advanced cases [cannon can be used](./cannon.md) to generate a +trace, including the claim values to use at specific steps. Note that it is not valid to create a game that disputes an +output root, using the final hash from a trace that confirms the output root is valid. To dispute an output root +successfully, the trace must resolve that the disputed output root is invalid. The game can then be created by calling the `create` method on the `DisputeGameFactory` contract. This requires three parameters: @@ -45,27 +45,28 @@ parameters: This emits a log event `DisputeGameCreated(gameAddress, gameType, rootClaim)` where `gameAddress` is the address of the newly created dispute game. -A simple helper script, [create_game.sh](../../op-challenger#create_gamesh) has been created to easily create a new -dispute game and also provides an example of using `cast` to manually create a game. +The helper script, [create_game.sh](../../op-challenger#create_gamesh) can be used to easily create a new dispute +game and also acts as an example of using `cast` to manually create a game. ## Performing Moves -The dispute game progresses by actors by countering existing claims via either the `attack` or `defend` methods in +The dispute game progresses by actors countering existing claims via either the `attack` or `defend` methods in the `FaultDisputeGame` contract. Note that only `attack` can be used to counter the root claim. In both cases, there are two inputs required: -- `parentIndex` - the index in the claims array of the parent claim that is being countered +- `parentIndex` - the index in the claims array of the parent claim that is being countered. - `claim` - a `bytes32` hash of the state at the trace index corresponding to the new claim’s position. -A simple helper script, [move.sh](../../op-challenger#movesh), has been created to easily perform moves and also -provides an example of using `cast` to manually call `attack` and `defend`. +The helper script, [move.sh](../../op-challenger#movesh), can be used to easily perform moves and also +acts as an example of using `cast` to manually call `attack` and `defend`. ## Performing Steps -Attack and defend can only be used until the maximum depth of the game is reached. To counter claims at the maximum -depth, a step must be performed instead. Calling the `step` method in the `FaultDisputeGame` contract counters a claim -at the maximum depth by running a single step of the cannon VM on chain. The `step` method will revert unless the cannon -execution confirms the claim being countered is invalid. +Attacking or defending are teh only available actions before the maximum depth of the game is reached. To counter claims +at the maximum depth, a step must be performed instead. Calling the `step` method in the `FaultDisputeGame` contract +counters a claim at the maximum depth by running a single step of the cannon VM on chain. The `step` method will revert +unless the cannon execution confirms the claim being countered is invalid. Note, if an actor's clock runs out at any +point, the game can be [resolved](#resolving-a-game). The inputs for step are: @@ -74,14 +75,14 @@ The inputs for step are: - `stateData` - the full cannon state witness to use as the starting state for execution - `proof` - the additional proof data for the state witness required by cannon to perform the step -When a step is attacking, the caller is making the claim that the claim at `claimIndex` is incorrect, and the claim for +When a step is attacking, the caller is asserting that the claim at `claimIndex` is incorrect, and the claim for the previous trace index (made at a previous level in the game) was correct. The `stateData` must be the pre-image for the agreed correct hash at the previous trace index. The call to `step` will revert if the post-state from cannon matches the claim at `claimIndex` since the on-chain execution has proven the claim correct and it should not be countered. -When a step is defending, the caller is making the claim that the claim at `claimIndex` is correct, and the claim for -the next trac index (made at a previous level in the game) is incorrect. The `stateData` must be the pre-image for the +When a step is defending, the caller is asserting that the claim at `claimIndex` is correct, and the claim for +the next trace index (made at a previous level in the game) is incorrect. The `stateData` must be the pre-image for the hash in the claim at `claimIndex`. The `step` function will revert with `ValidStep()` if the cannon execution proves that the claim attempting to be @@ -106,5 +107,5 @@ be resolved once. There are no inputs required for the `resolve` method. When successful, a log event is emitted with the game’s final status. -A helper script, [resolve.sh](../../op-challenger#resolvesh), has been created to easily resolve a game and also -provides an example of using `cast` to manually call `resolve` and understand the result. +The helper script, [resolve.sh](../../op-challenger#resolvesh), can be used to easily resolve a game and also acts as an +example of using `cast` to manually call `resolve` and understand the result. diff --git a/docs/fault-proof-alpha/run-challenger.md b/docs/fault-proof-alpha/run-challenger.md index 5e23c58cc..c7ed6af0a 100644 --- a/docs/fault-proof-alpha/run-challenger.md +++ b/docs/fault-proof-alpha/run-challenger.md @@ -18,7 +18,18 @@ ### Starting op-challenger -In the top level of the monorepo, replace the placeholders and then run: +When executing `op-challenger`, there are a few placeholders that need to be set to concreate values: + +- `` the Goerli L1 JSON RPC endpoint +- `` the address of the dispute game factory contract (see + the [Goerli deployment details](./deployments.md#goerli)) +- `` the prestate.json downloaded above. Note that this needs to precisely match the prestate used on-chain so + must be the downloaded version and not a version built locally (see the [Goerli deployment details](./deployments.md#goerli)) +- `` the OP-Goerli L2 archive node JSON RPC endpoint +- `` the private key for a funded Goerli account. For other ways to specify the account to use + see `./op-challenger/bin/op-challenger --help` + +From inside the monorepo directory, run the challenger with these placeholders set. ```bash # Build the required components @@ -39,16 +50,6 @@ make op-challenger op-program cannon --private-key ``` -The placeholders are: - -- `` the Goerli L1 JSON RPC endpoint -- `` the address of the dispute game factory contract (see - the [Goerli deployment details](./deployments.md#goerli)) -- `` the prestate.json downloaded above. Note that this needs to precisely match the prestate used on-chain so - must be the downloaded version and not a version built locally (see the [Goerli deployment details](./deployments.md#goerli)) -- `` the OP-Goerli L2 archive node JSON RPC endpoint -- `` the private key for a funded Goerli account. For other ways to specify the account to use - see `./op-challenger/bin/op-challenger --help` ### Restricting Games to Play From fdfa5df37b868b0a120b1ebc2c7f016737959fed Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Wed, 6 Sep 2023 14:56:16 +1000 Subject: [PATCH 32/59] Create an e2e test showing cannon proving an output root is invalid --- op-e2e/e2eutils/disputegame/helper.go | 37 ++------ op-e2e/e2eutils/l2oo/helper.go | 130 ++++++++++++++++++++++++++ op-e2e/e2eutils/wait/waits.go | 13 +++ op-e2e/faultproof_test.go | 78 ++++++++++++++++ 4 files changed, 228 insertions(+), 30 deletions(-) create mode 100644 op-e2e/e2eutils/l2oo/helper.go diff --git a/op-e2e/e2eutils/disputegame/helper.go b/op-e2e/e2eutils/disputegame/helper.go index f13860fff..c027d63b2 100644 --- a/op-e2e/e2eutils/disputegame/helper.go +++ b/op-e2e/e2eutils/disputegame/helper.go @@ -16,6 +16,7 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon" "github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/l2oo" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-node/rollup" @@ -65,7 +66,7 @@ type FactoryHelper struct { factoryAddr common.Address factory *bindings.DisputeGameFactory blockOracle *bindings.BlockOracle - l2oo *bindings.L2OutputOracleCaller + l2ooHelper *l2oo.L2OOHelper } func NewFactoryHelper(t *testing.T, ctx context.Context, deployments *genesis.L1Deployments, client *ethclient.Client) *FactoryHelper { @@ -81,8 +82,6 @@ func NewFactoryHelper(t *testing.T, ctx context.Context, deployments *genesis.L1 require.NoError(err) blockOracle, err := bindings.NewBlockOracle(deployments.BlockOracle, client) require.NoError(err) - l2oo, err := bindings.NewL2OutputOracleCaller(deployments.L2OutputOracleProxy, client) - require.NoError(err, "Error creating l2oo caller") return &FactoryHelper{ t: t, @@ -92,7 +91,7 @@ func NewFactoryHelper(t *testing.T, ctx context.Context, deployments *genesis.L1 factory: factory, factoryAddr: factoryAddr, blockOracle: blockOracle, - l2oo: l2oo, + l2ooHelper: l2oo.NewL2OOHelperReadOnly(t, deployments, client), } } @@ -150,12 +149,8 @@ func (h *FactoryHelper) StartCannonGameWithCorrectRoot(ctx context.Context, roll challengerOpts = append(challengerOpts, options...) cfg := challenger.NewChallengerConfig(h.t, l1Endpoint, challengerOpts...) opts := &bind.CallOpts{Context: ctx} - outputIdx, err := h.l2oo.GetL2OutputIndexAfter(opts, new(big.Int).SetUint64(l2BlockNumber)) - h.require.NoError(err, "Fetch challenged output index") - challengedOutput, err := h.l2oo.GetL2Output(opts, outputIdx) - h.require.NoError(err, "Fetch challenged output") - agreedOutput, err := h.l2oo.GetL2Output(opts, new(big.Int).Sub(outputIdx, common.Big1)) - h.require.NoError(err, "Fetch agreed output") + challengedOutput := h.l2ooHelper.GetL2OutputAfter(ctx, l2BlockNumber) + agreedOutput := h.l2ooHelper.GetL2OutputBefore(ctx, l2BlockNumber) l1BlockInfo, err := h.blockOracle.Load(opts, l1Head) h.require.NoError(err, "Fetch L1 block info") @@ -246,26 +241,8 @@ func (h *FactoryHelper) prepareCannonGame(ctx context.Context) (uint64, *big.Int func (h *FactoryHelper) waitForProposals(ctx context.Context) uint64 { ctx, cancel := context.WithTimeout(ctx, 2*time.Minute) defer cancel() - opts := &bind.CallOpts{Context: ctx} - latestOutputIndex, err := wait.AndGet( - ctx, - time.Second, - func() (*big.Int, error) { - index, err := h.l2oo.LatestOutputIndex(opts) - if err != nil { - h.t.Logf("Could not get latest output index: %v", err.Error()) - return nil, nil - } - h.t.Logf("Latest output index: %v", index) - return index, nil - }, - func(index *big.Int) bool { - return index != nil && index.Cmp(big.NewInt(1)) >= 0 - }) - h.require.NoError(err, "Did not get two output roots") - output, err := h.l2oo.GetL2Output(opts, latestOutputIndex) - h.require.NoErrorf(err, "Could not get latst output root index: %v", latestOutputIndex) - return output.L2BlockNumber.Uint64() + latestOutputIdx := h.l2ooHelper.WaitForProposals(ctx, 2) + return h.l2ooHelper.GetL2Output(ctx, latestOutputIdx).L2BlockNumber.Uint64() } // checkpointL1Block stores the current L1 block in the oracle diff --git a/op-e2e/e2eutils/l2oo/helper.go b/op-e2e/e2eutils/l2oo/helper.go new file mode 100644 index 000000000..47676e7c6 --- /dev/null +++ b/op-e2e/e2eutils/l2oo/helper.go @@ -0,0 +1,130 @@ +package l2oo + +import ( + "context" + "crypto/ecdsa" + "math/big" + "testing" + "time" + + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +type L2OOHelper struct { + t *testing.T + require *require.Assertions + client *ethclient.Client + l2oo *bindings.L2OutputOracle + + // Nil when read-only + transactOpts *bind.TransactOpts + rollupCfg *rollup.Config +} + +func NewL2OOHelperReadOnly(t *testing.T, deployments *genesis.L1Deployments, client *ethclient.Client) *L2OOHelper { + require := require.New(t) + l2oo, err := bindings.NewL2OutputOracle(deployments.L2OutputOracleProxy, client) + require.NoError(err, "Error creating l2oo bindings") + + return &L2OOHelper{ + t: t, + require: require, + client: client, + l2oo: l2oo, + } +} + +func NewL2OOHelper(t *testing.T, deployments *genesis.L1Deployments, client *ethclient.Client, proposerKey *ecdsa.PrivateKey, rollupCfg *rollup.Config) *L2OOHelper { + h := NewL2OOHelperReadOnly(t, deployments, client) + + chainID, err := client.ChainID(context.Background()) + h.require.NoError(err, "Failed to get chain ID") + transactOpts, err := bind.NewKeyedTransactorWithChainID(proposerKey, chainID) + h.require.NoError(err) + h.transactOpts = transactOpts + h.rollupCfg = rollupCfg + return h +} + +// WaitForProposals waits until there are at least the specified number of proposals in the output oracle +// Returns the index of the latest output proposal +func (h *L2OOHelper) WaitForProposals(ctx context.Context, req int64) uint64 { + ctx, cancel := context.WithTimeout(ctx, 2*time.Minute) + defer cancel() + opts := &bind.CallOpts{Context: ctx} + latestOutputIndex, err := wait.AndGet( + ctx, + time.Second, + func() (*big.Int, error) { + index, err := h.l2oo.LatestOutputIndex(opts) + if err != nil { + h.t.Logf("Could not get latest output index: %v", err.Error()) + return nil, nil + } + h.t.Logf("Latest output index: %v", index) + return index, nil + }, + func(index *big.Int) bool { + return index != nil && index.Cmp(big.NewInt(req-1)) >= 0 + }) + h.require.NoErrorf(err, "Did not get %v output roots", req) + return latestOutputIndex.Uint64() +} + +func (h *L2OOHelper) GetL2Output(ctx context.Context, idx uint64) bindings.TypesOutputProposal { + output, err := h.l2oo.GetL2Output(&bind.CallOpts{Context: ctx}, new(big.Int).SetUint64(idx)) + h.require.NoErrorf(err, "Failed to get output root at index: %v", idx) + return output +} + +func (h *L2OOHelper) GetL2OutputAfter(ctx context.Context, l2BlockNum uint64) bindings.TypesOutputProposal { + opts := &bind.CallOpts{Context: ctx} + outputIdx, err := h.l2oo.GetL2OutputIndexAfter(opts, new(big.Int).SetUint64(l2BlockNum)) + h.require.NoError(err, "Fetch challenged output index") + output, err := h.l2oo.GetL2Output(opts, outputIdx) + h.require.NoError(err, "Fetch challenged output") + return output +} + +func (h *L2OOHelper) GetL2OutputBefore(ctx context.Context, l2BlockNum uint64) bindings.TypesOutputProposal { + opts := &bind.CallOpts{Context: ctx} + latestBlockNum, err := h.l2oo.LatestBlockNumber(opts) + h.require.NoError(err, "Failed to get latest output root block number") + var outputIdx *big.Int + if latestBlockNum.Uint64() < l2BlockNum { + outputIdx, err = h.l2oo.LatestOutputIndex(opts) + h.require.NoError(err, "Failed to get latest output index") + } else { + outputIdx, err = h.l2oo.GetL2OutputIndexAfter(opts, new(big.Int).SetUint64(l2BlockNum)) + h.require.NoErrorf(err, "Failed to get output index after block %v", l2BlockNum) + h.require.NotZerof(outputIdx.Uint64(), "No l2 output before block %v", l2BlockNum) + outputIdx = new(big.Int).Sub(outputIdx, common.Big1) + } + return h.GetL2Output(ctx, outputIdx.Uint64()) +} + +func (h *L2OOHelper) PublishNextOutput(ctx context.Context, outputRoot common.Hash) { + h.require.NotNil(h.transactOpts, "Can't publish outputs from a read only L2OOHelper") + nextBlockNum, err := h.l2oo.NextBlockNumber(&bind.CallOpts{Context: ctx}) + h.require.NoError(err, "Should get next block number") + + genesis := h.rollupCfg.Genesis + targetTimestamp := genesis.L2Time + ((nextBlockNum.Uint64() - genesis.L2.Number) * h.rollupCfg.BlockTime) + timedCtx, cancel := context.WithTimeout(ctx, 30*time.Second) + defer cancel() + h.require.NoErrorf( + wait.ForBlockWithTimestamp(timedCtx, h.client, targetTimestamp), + "Wait for L1 block with timestamp >= %v", targetTimestamp) + + tx, err := h.l2oo.ProposeL2Output(h.transactOpts, outputRoot, nextBlockNum, [32]byte{}, common.Big0) + h.require.NoErrorf(err, "Failed to propose output root for l2 block number %v", nextBlockNum) + _, err = wait.ForReceiptOK(ctx, h.client, tx.Hash()) + h.require.NoErrorf(err, "Proposal for l2 block %v failed", nextBlockNum) +} diff --git a/op-e2e/e2eutils/wait/waits.go b/op-e2e/e2eutils/wait/waits.go index 558304d0a..bea94ea8d 100644 --- a/op-e2e/e2eutils/wait/waits.go +++ b/op-e2e/e2eutils/wait/waits.go @@ -85,6 +85,19 @@ func ForBlock(ctx context.Context, client *ethclient.Client, n uint64) error { return nil } +func ForBlockWithTimestamp(ctx context.Context, client *ethclient.Client, target uint64) error { + _, err := AndGet(ctx, time.Second, func() (uint64, error) { + head, err := client.BlockByNumber(ctx, nil) + if err != nil { + return 0, err + } + return head.Time(), nil + }, func(actual uint64) bool { + return actual >= target + }) + return err +} + func ForNextBlock(ctx context.Context, client *ethclient.Client) error { current, err := client.BlockNumber(ctx) if err != nil { diff --git a/op-e2e/faultproof_test.go b/op-e2e/faultproof_test.go index d40a7080e..b357e355e 100644 --- a/op-e2e/faultproof_test.go +++ b/op-e2e/faultproof_test.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame" + l2oo2 "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/l2oo" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" @@ -355,6 +356,83 @@ func TestCannonDefendStep(t *testing.T) { game.LogGameData(ctx) } +func TestCannonProposedOutputRootInvalid(t *testing.T) { + InitParallel(t) + + ctx := context.Background() + sys, l1Client, game, correctTrace := setupDisputeGameForInvalidOutputRoot(t, common.Hash{0xab}) + t.Cleanup(sys.Close) + + maxDepth := game.MaxDepth(ctx) + + // Now maliciously play the game and it should be impossible to win + + for claimCount := int64(1); claimCount < maxDepth; { + // Attack everything but oddly using the correct hash. + correctTrace.Attack(ctx, claimCount-1) + claimCount++ + game.LogGameData(ctx) + game.WaitForClaimCount(ctx, claimCount) + + game.LogGameData(ctx) + // Wait for the challenger to counter + claimCount++ + game.WaitForClaimCount(ctx, claimCount) + } + + game.LogGameData(ctx) + // Wait for the challenger to call step and counter our invalid claim + game.WaitForClaimAtMaxDepth(ctx, false) + + // It's on us to call step if we want to win but shouldn't be possible + // Need to add support for this to the helper + + // Time travel past when the game will be resolvable. + sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx)) + require.NoError(t, wait.ForNextBlock(ctx, l1Client)) + + game.WaitForGameStatus(ctx, disputegame.StatusDefenderWins) + game.LogGameData(ctx) +} + +// setupDisputeGameForInvalidOutputRoot sets up an L2 chain with at least one valid output root followed by an invalid output root. +// A cannon dispute game is started to dispute the invalid output root with the correct root claim provided. +// An honest challenger is run to defend the root claim (ie disagree with the invalid output root). +func setupDisputeGameForInvalidOutputRoot(t *testing.T, outputRoot common.Hash) (*System, *ethclient.Client, *disputegame.CannonGameHelper, *disputegame.HonestHelper) { + ctx := context.Background() + sys, l1Client := startFaultDisputeSystem(t) + + l2oo := l2oo2.NewL2OOHelper(t, sys.cfg.L1Deployments, l1Client, sys.cfg.Secrets.Proposer, sys.RollupConfig) + + // Wait for one valid output root to be submitted + l2oo.WaitForProposals(ctx, 1) + + // Stop the honest output submitter so we can publish invalid outputs + sys.L2OutputSubmitter.Stop() + sys.L2OutputSubmitter = nil + + // Submit an invalid output rooot + l2oo.PublishNextOutput(ctx, outputRoot) + + l1Endpoint := sys.NodeEndpoint("l1") + l2Endpoint := sys.NodeEndpoint("sequencer") + + // Dispute the new output root by creating a new game with the correct cannon trace. + disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys.cfg.L1Deployments, l1Client) + game, correctTrace := disputeGameFactory.StartCannonGameWithCorrectRoot(ctx, sys.RollupConfig, sys.L2GenesisCfg, l1Endpoint, l2Endpoint, + challenger.WithPrivKey(sys.cfg.Secrets.Mallory), + ) + require.NotNil(t, game) + + // Start the honest challenger + game.StartChallenger(ctx, sys.RollupConfig, sys.L2GenesisCfg, l1Endpoint, l2Endpoint, "Defender", + // Disagree with the proposed output, so agree with the (correct) root claim + challenger.WithAgreeProposedOutput(false), + challenger.WithPrivKey(sys.cfg.Secrets.Mallory), + ) + return sys, l1Client, game, correctTrace +} + func TestCannonChallengeWithCorrectRoot(t *testing.T) { t.Skip("Not currently handling this case as the correct approach will change when output root bisection is added") InitParallel(t) From b6cae656627c60de6ff7e299f35a499246d1eafc Mon Sep 17 00:00:00 2001 From: Will Cory Date: Mon, 28 Aug 2023 15:18:04 -0700 Subject: [PATCH 33/59] feat(indexer): Add metrics to indexer/api --- indexer/api/api.go | 46 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/indexer/api/api.go b/indexer/api/api.go index 94cbade08..6f74cec7a 100644 --- a/indexer/api/api.go +++ b/indexer/api/api.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum-optimism/optimism/indexer/api/routes" "github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/op-service/httputil" + "github.com/ethereum-optimism/optimism/op-service/metrics" "github.com/ethereum/go-ethereum/log" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" @@ -16,19 +17,34 @@ import ( const ethereumAddressRegex = `^0x[a-fA-F0-9]{40}$` type Api struct { - log log.Logger - Router *chi.Mux + log log.Logger + Router *chi.Mux + MetricsRouter *chi.Mux } +const ( + MetricsNamespace = "op_indexer" +) + func NewApi(logger log.Logger, bv database.BridgeTransfersView) *Api { - r := chi.NewRouter() - h := routes.NewRoutes(logger, bv, r) + apiRouter := chi.NewRouter() + h := routes.NewRoutes(logger, bv, apiRouter) + + apiRouter.Use(middleware.Heartbeat("/healthz")) + + apiRouter.Get(fmt.Sprintf("/api/v0/deposits/{address:%s}", ethereumAddressRegex), h.L1DepositsHandler) + apiRouter.Get(fmt.Sprintf("/api/v0/withdrawals/{address:%s}", ethereumAddressRegex), h.L2WithdrawalsHandler) + + metricsRouter := chi.NewRouter() + registry := metrics.NewRegistry() + promRecorder := metrics.NewPromHTTPRecorder(registry, MetricsNamespace) + promHandler := metrics.NewHTTPRecordingMiddleware(promRecorder, apiRouter) - r.Use(middleware.Heartbeat("/healthz")) + metricsRouter.Use(middleware.Heartbeat("/healthz")) - r.Get(fmt.Sprintf("/api/v0/deposits/{address:%s}", ethereumAddressRegex), h.L1DepositsHandler) - r.Get(fmt.Sprintf("/api/v0/withdrawals/{address:%s}", ethereumAddressRegex), h.L2WithdrawalsHandler) - return &Api{log: logger, Router: r} + metricsRouter.Get("/metrics", promHandler.ServeHTTP) + + return &Api{log: logger, Router: apiRouter, MetricsRouter: metricsRouter} } func (a *Api) Listen(ctx context.Context, port int) error { @@ -43,3 +59,17 @@ func (a *Api) Listen(ctx context.Context, port int) error { return err } + +func (a *Api) ListenMetrics(ctx context.Context, port int) error { + a.log.Info("metrics server listening...", "port", port) + + server := http.Server{Addr: fmt.Sprintf(":%d", port), Handler: a.MetricsRouter} + err := httputil.ListenAndServeContext(ctx, &server) + if err != nil { + a.log.Error("api server stopped", "err", err) + } else { + a.log.Info("api server stopped") + } + + return err +} From 9bc31f6b7db04870abe1f201a40234db54c96ca1 Mon Sep 17 00:00:00 2001 From: Will Cory Date: Mon, 28 Aug 2023 15:22:34 -0700 Subject: [PATCH 34/59] feat(indexer): Connect api metrics to cli --- indexer/cmd/indexer/cli.go | 56 +++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/indexer/cmd/indexer/cli.go b/indexer/cmd/indexer/cli.go index ba8b69d62..65e235a8f 100644 --- a/indexer/cmd/indexer/cli.go +++ b/indexer/cmd/indexer/cli.go @@ -66,6 +66,53 @@ func runApi(ctx *cli.Context) error { return api.Listen(ctx.Context, cfg.HTTPServer.Port) } +func runApiMetrics(ctx *cli.Context) error { + log := log.NewLogger(log.ReadCLIConfig(ctx)).New("role", "api") + cfg, err := config.LoadConfig(log, ctx.String(ConfigFlag.Name)) + if err != nil { + log.Error("failed to load config", "err", err) + return err + } + + db, err := database.NewDB(cfg.DB) + if err != nil { + log.Error("failed to connect to database", "err", err) + return err + } + + api := api.NewApi(log, db.BridgeTransfers) + return api.Listen(ctx.Context, cfg.Metrics.Port) +} + +func runApiAndMetrics(ctx *cli.Context) error { + log := log.NewLogger(log.ReadCLIConfig(ctx)) + + // Ensure both processes complete before returning. + var wg sync.WaitGroup + wg.Add(2) + + go func() { + defer wg.Done() + err := runApi(ctx) + if err != nil { + log.Error("api process non-zero exit", "err", err) + } + }() + go func() { + defer wg.Done() + err := runApiMetrics(ctx) + if err != nil { + log.Error("indexer process non-zero exit", "err", err) + } + }() + + // We purposefully return no error since the indexer and api + // have no inter-dependencies. We simply rely on the logs to + // report a non-zero exit for either process. + wg.Wait() + return nil +} + func runAll(ctx *cli.Context) error { log := log.NewLogger(log.ReadCLIConfig(ctx)) @@ -87,6 +134,13 @@ func runAll(ctx *cli.Context) error { log.Error("indexer process non-zero exit", "err", err) } }() + go func() { + defer wg.Done() + err := runApiMetrics(ctx) + if err != nil { + log.Error("indexer process non-zero exit", "err", err) + } + }() // We purposefully return no error since the indexer and api // have no inter-dependencies. We simply rely on the logs to @@ -107,7 +161,7 @@ func newCli(GitCommit string, GitDate string) *cli.App { Name: "api", Flags: flags, Description: "Runs the api service", - Action: runApi, + Action: runApiAndMetrics, }, { Name: "index", From 9e1efe4aa3e9c00d6f0b993bc6522dde4924dc2b Mon Sep 17 00:00:00 2001 From: Will Cory Date: Tue, 29 Aug 2023 12:41:52 -0700 Subject: [PATCH 35/59] refactors --- indexer/api/api.go | 85 ++++++++++++++++++++++++++++---------- indexer/api/api_test.go | 16 +++++-- indexer/cmd/indexer/cli.go | 9 +--- 3 files changed, 77 insertions(+), 33 deletions(-) diff --git a/indexer/api/api.go b/indexer/api/api.go index 6f74cec7a..4e9a59ec5 100644 --- a/indexer/api/api.go +++ b/indexer/api/api.go @@ -4,72 +4,113 @@ import ( "context" "fmt" "net/http" + "runtime/debug" + "sync" "github.com/ethereum-optimism/optimism/indexer/api/routes" + "github.com/ethereum-optimism/optimism/indexer/config" "github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/op-service/httputil" "github.com/ethereum-optimism/optimism/op-service/metrics" "github.com/ethereum/go-ethereum/log" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" + "github.com/prometheus/client_golang/prometheus" ) const ethereumAddressRegex = `^0x[a-fA-F0-9]{40}$` type Api struct { - log log.Logger - Router *chi.Mux - MetricsRouter *chi.Mux + log log.Logger + Router *chi.Mux + apiConfig config.APIConfig + metricsConfig config.MetricsConfig + metricsRegistry *prometheus.Registry } const ( MetricsNamespace = "op_indexer" ) -func NewApi(logger log.Logger, bv database.BridgeTransfersView) *Api { +func ChiMetricsMiddleware(rec metrics.HTTPRecorder) func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return metrics.NewHTTPRecordingMiddleware(rec, next) + } +} + +func NewApi(logger log.Logger, bv database.BridgeTransfersView, apiConfig config.APIConfig, metricsConfig config.MetricsConfig) *Api { apiRouter := chi.NewRouter() h := routes.NewRoutes(logger, bv, apiRouter) + mr := metrics.NewRegistry() + promRecorder := metrics.NewPromHTTPRecorder(mr, MetricsNamespace) + + apiRouter.Use(ChiMetricsMiddleware(promRecorder)) apiRouter.Use(middleware.Heartbeat("/healthz")) apiRouter.Get(fmt.Sprintf("/api/v0/deposits/{address:%s}", ethereumAddressRegex), h.L1DepositsHandler) apiRouter.Get(fmt.Sprintf("/api/v0/withdrawals/{address:%s}", ethereumAddressRegex), h.L2WithdrawalsHandler) - metricsRouter := chi.NewRouter() - registry := metrics.NewRegistry() - promRecorder := metrics.NewPromHTTPRecorder(registry, MetricsNamespace) - promHandler := metrics.NewHTTPRecordingMiddleware(promRecorder, apiRouter) + return &Api{log: logger, Router: apiRouter, metricsRegistry: mr, metricsConfig: metricsConfig, apiConfig: apiConfig} +} - metricsRouter.Use(middleware.Heartbeat("/healthz")) +func (a *Api) Start(ctx context.Context) error { + var wg sync.WaitGroup + errCh := make(chan error, 2) + + processCtx, processCancel := context.WithCancel(ctx) + runProcess := func(start func(ctx context.Context) error) { + wg.Add(1) + go func() { + defer func() { + if err := recover(); err != nil { + a.log.Error("halting api on panic", "err", err) + debug.PrintStack() + errCh <- fmt.Errorf("panic: %v", err) + } + + processCancel() + wg.Done() + }() + + errCh <- start(processCtx) + }() + } - metricsRouter.Get("/metrics", promHandler.ServeHTTP) + runProcess(a.startServer) + runProcess(a.startMetricsServer) - return &Api{log: logger, Router: apiRouter, MetricsRouter: metricsRouter} -} + wg.Wait() -func (a *Api) Listen(ctx context.Context, port int) error { - a.log.Info("api server listening...", "port", port) - server := http.Server{Addr: fmt.Sprintf(":%d", port), Handler: a.Router} - err := httputil.ListenAndServeContext(ctx, &server) + err := <-errCh if err != nil { - a.log.Error("api server stopped", "err", err) + a.log.Error("api stopped", "err", err) } else { - a.log.Info("api server stopped") + a.log.Info("api stopped") } return err } -func (a *Api) ListenMetrics(ctx context.Context, port int) error { - a.log.Info("metrics server listening...", "port", port) - - server := http.Server{Addr: fmt.Sprintf(":%d", port), Handler: a.MetricsRouter} +func (a *Api) startServer(ctx context.Context) error { + a.log.Info("api server listening...", "port", a.apiConfig.Port) + server := http.Server{Addr: fmt.Sprintf(":%d", a.apiConfig.Port), Handler: a.Router} err := httputil.ListenAndServeContext(ctx, &server) if err != nil { a.log.Error("api server stopped", "err", err) } else { a.log.Info("api server stopped") } + return err +} +func (a *Api) startMetricsServer(ctx context.Context) error { + a.log.Info("starting metrics server...", "port", a.metricsConfig.Port) + err := metrics.ListenAndServe(ctx, a.metricsRegistry, a.metricsConfig.Host, a.metricsConfig.Port) + if err != nil { + a.log.Error("metrics server stopped", "err", err) + } else { + a.log.Info("metrics server stopped") + } return err } diff --git a/indexer/api/api_test.go b/indexer/api/api_test.go index 9ebe02959..43beb103b 100644 --- a/indexer/api/api_test.go +++ b/indexer/api/api_test.go @@ -6,6 +6,7 @@ import ( "net/http/httptest" "testing" + "github.com/ethereum-optimism/optimism/indexer/config" "github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum/go-ethereum/common" @@ -18,6 +19,15 @@ type MockBridgeTransfersView struct{} var mockAddress = "0x4204204204204204204204204204204204204204" +var apiConfig = config.APIConfig{ + Host: "localhost", + Port: 8080, +} +var metricsConfig = config.MetricsConfig{ + Host: "localhost", + Port: 7300, +} + var ( deposit = database.L1BridgeDeposit{ TransactionSourceHash: common.HexToHash("abc"), @@ -77,7 +87,7 @@ func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalsByAddress(address common. } func TestHealthz(t *testing.T) { logger := testlog.Logger(t, log.LvlInfo) - api := NewApi(logger, &MockBridgeTransfersView{}) + api := NewApi(logger, &MockBridgeTransfersView{}, apiConfig, metricsConfig) request, err := http.NewRequest("GET", "/healthz", nil) assert.Nil(t, err) @@ -89,7 +99,7 @@ func TestHealthz(t *testing.T) { func TestL1BridgeDepositsHandler(t *testing.T) { logger := testlog.Logger(t, log.LvlInfo) - api := NewApi(logger, &MockBridgeTransfersView{}) + api := NewApi(logger, &MockBridgeTransfersView{}, apiConfig, metricsConfig) request, err := http.NewRequest("GET", fmt.Sprintf("/api/v0/deposits/%s", mockAddress), nil) assert.Nil(t, err) @@ -101,7 +111,7 @@ func TestL1BridgeDepositsHandler(t *testing.T) { func TestL2BridgeWithdrawalsByAddressHandler(t *testing.T) { logger := testlog.Logger(t, log.LvlInfo) - api := NewApi(logger, &MockBridgeTransfersView{}) + api := NewApi(logger, &MockBridgeTransfersView{}, apiConfig, metricsConfig) request, err := http.NewRequest("GET", fmt.Sprintf("/api/v0/withdrawals/%s", mockAddress), nil) assert.Nil(t, err) diff --git a/indexer/cmd/indexer/cli.go b/indexer/cmd/indexer/cli.go index 65e235a8f..d949415fd 100644 --- a/indexer/cmd/indexer/cli.go +++ b/indexer/cmd/indexer/cli.go @@ -134,13 +134,6 @@ func runAll(ctx *cli.Context) error { log.Error("indexer process non-zero exit", "err", err) } }() - go func() { - defer wg.Done() - err := runApiMetrics(ctx) - if err != nil { - log.Error("indexer process non-zero exit", "err", err) - } - }() // We purposefully return no error since the indexer and api // have no inter-dependencies. We simply rely on the logs to @@ -161,7 +154,7 @@ func newCli(GitCommit string, GitDate string) *cli.App { Name: "api", Flags: flags, Description: "Runs the api service", - Action: runApiAndMetrics, + Action: runApi, }, { Name: "index", From ea7e4f3752b5cdfe984b81c629102b0527216ca4 Mon Sep 17 00:00:00 2001 From: Will Cory Date: Tue, 5 Sep 2023 23:38:48 -0700 Subject: [PATCH 36/59] lowercase --- indexer/api/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indexer/api/api.go b/indexer/api/api.go index 4e9a59ec5..ca784e388 100644 --- a/indexer/api/api.go +++ b/indexer/api/api.go @@ -32,7 +32,7 @@ const ( MetricsNamespace = "op_indexer" ) -func ChiMetricsMiddleware(rec metrics.HTTPRecorder) func(http.Handler) http.Handler { +func chiMetricsMiddleware(rec metrics.HTTPRecorder) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return metrics.NewHTTPRecordingMiddleware(rec, next) } From 5192ff2cdbb2b02d635b0d416732ce163ed8e5f9 Mon Sep 17 00:00:00 2001 From: Will Cory Date: Tue, 5 Sep 2023 23:46:45 -0700 Subject: [PATCH 37/59] :bug: bad rebase --- indexer/api/api.go | 14 +++++------ indexer/api/api_test.go | 4 +-- indexer/cmd/indexer/cli.go | 51 ++------------------------------------ 3 files changed, 11 insertions(+), 58 deletions(-) diff --git a/indexer/api/api.go b/indexer/api/api.go index ca784e388..7604be3e3 100644 --- a/indexer/api/api.go +++ b/indexer/api/api.go @@ -23,8 +23,8 @@ const ethereumAddressRegex = `^0x[a-fA-F0-9]{40}$` type Api struct { log log.Logger Router *chi.Mux - apiConfig config.APIConfig - metricsConfig config.MetricsConfig + serverConfig config.ServerConfig + metricsConfig config.ServerConfig metricsRegistry *prometheus.Registry } @@ -38,20 +38,20 @@ func chiMetricsMiddleware(rec metrics.HTTPRecorder) func(http.Handler) http.Hand } } -func NewApi(logger log.Logger, bv database.BridgeTransfersView, apiConfig config.APIConfig, metricsConfig config.MetricsConfig) *Api { +func NewApi(logger log.Logger, bv database.BridgeTransfersView, serverConfig config.ServerConfig, metricsConfig config.ServerConfig) *Api { apiRouter := chi.NewRouter() h := routes.NewRoutes(logger, bv, apiRouter) mr := metrics.NewRegistry() promRecorder := metrics.NewPromHTTPRecorder(mr, MetricsNamespace) - apiRouter.Use(ChiMetricsMiddleware(promRecorder)) + apiRouter.Use(chiMetricsMiddleware(promRecorder)) apiRouter.Use(middleware.Heartbeat("/healthz")) apiRouter.Get(fmt.Sprintf("/api/v0/deposits/{address:%s}", ethereumAddressRegex), h.L1DepositsHandler) apiRouter.Get(fmt.Sprintf("/api/v0/withdrawals/{address:%s}", ethereumAddressRegex), h.L2WithdrawalsHandler) - return &Api{log: logger, Router: apiRouter, metricsRegistry: mr, metricsConfig: metricsConfig, apiConfig: apiConfig} + return &Api{log: logger, Router: apiRouter, metricsRegistry: mr, serverConfig: serverConfig, metricsConfig: metricsConfig} } func (a *Api) Start(ctx context.Context) error { @@ -93,8 +93,8 @@ func (a *Api) Start(ctx context.Context) error { } func (a *Api) startServer(ctx context.Context) error { - a.log.Info("api server listening...", "port", a.apiConfig.Port) - server := http.Server{Addr: fmt.Sprintf(":%d", a.apiConfig.Port), Handler: a.Router} + a.log.Info("api server listening...", "port", a.serverConfig.Port) + server := http.Server{Addr: fmt.Sprintf(":%d", a.serverConfig.Port), Handler: a.Router} err := httputil.ListenAndServeContext(ctx, &server) if err != nil { a.log.Error("api server stopped", "err", err) diff --git a/indexer/api/api_test.go b/indexer/api/api_test.go index 43beb103b..7b99bb8b8 100644 --- a/indexer/api/api_test.go +++ b/indexer/api/api_test.go @@ -19,11 +19,11 @@ type MockBridgeTransfersView struct{} var mockAddress = "0x4204204204204204204204204204204204204204" -var apiConfig = config.APIConfig{ +var apiConfig = config.ServerConfig{ Host: "localhost", Port: 8080, } -var metricsConfig = config.MetricsConfig{ +var metricsConfig = config.ServerConfig{ Host: "localhost", Port: 7300, } diff --git a/indexer/cmd/indexer/cli.go b/indexer/cmd/indexer/cli.go index d949415fd..e21b84b57 100644 --- a/indexer/cmd/indexer/cli.go +++ b/indexer/cmd/indexer/cli.go @@ -62,55 +62,8 @@ func runApi(ctx *cli.Context) error { } defer db.Close() - api := api.NewApi(log, db.BridgeTransfers) - return api.Listen(ctx.Context, cfg.HTTPServer.Port) -} - -func runApiMetrics(ctx *cli.Context) error { - log := log.NewLogger(log.ReadCLIConfig(ctx)).New("role", "api") - cfg, err := config.LoadConfig(log, ctx.String(ConfigFlag.Name)) - if err != nil { - log.Error("failed to load config", "err", err) - return err - } - - db, err := database.NewDB(cfg.DB) - if err != nil { - log.Error("failed to connect to database", "err", err) - return err - } - - api := api.NewApi(log, db.BridgeTransfers) - return api.Listen(ctx.Context, cfg.Metrics.Port) -} - -func runApiAndMetrics(ctx *cli.Context) error { - log := log.NewLogger(log.ReadCLIConfig(ctx)) - - // Ensure both processes complete before returning. - var wg sync.WaitGroup - wg.Add(2) - - go func() { - defer wg.Done() - err := runApi(ctx) - if err != nil { - log.Error("api process non-zero exit", "err", err) - } - }() - go func() { - defer wg.Done() - err := runApiMetrics(ctx) - if err != nil { - log.Error("indexer process non-zero exit", "err", err) - } - }() - - // We purposefully return no error since the indexer and api - // have no inter-dependencies. We simply rely on the logs to - // report a non-zero exit for either process. - wg.Wait() - return nil + api := api.NewApi(log, db.BridgeTransfers, cfg.HTTPServer, cfg.MetricsServer) + return api.Start(ctx.Context) } func runAll(ctx *cli.Context) error { From 3c6e59bb9aebe28e375dcab14e33633577e090ce Mon Sep 17 00:00:00 2001 From: Will Cory Date: Mon, 28 Aug 2023 16:06:59 -0700 Subject: [PATCH 38/59] feat(indexer): add recoverer middleware --- indexer/api/api.go | 1 + 1 file changed, 1 insertion(+) diff --git a/indexer/api/api.go b/indexer/api/api.go index 7604be3e3..261ce1e14 100644 --- a/indexer/api/api.go +++ b/indexer/api/api.go @@ -46,6 +46,7 @@ func NewApi(logger log.Logger, bv database.BridgeTransfersView, serverConfig con promRecorder := metrics.NewPromHTTPRecorder(mr, MetricsNamespace) apiRouter.Use(chiMetricsMiddleware(promRecorder)) + apiRouter.Use(middleware.Recoverer) apiRouter.Use(middleware.Heartbeat("/healthz")) apiRouter.Get(fmt.Sprintf("/api/v0/deposits/{address:%s}", ethereumAddressRegex), h.L1DepositsHandler) From 1857d617929df0c1a932638ff89572be85fdbf8c Mon Sep 17 00:00:00 2001 From: Will Cory Date: Thu, 31 Aug 2023 19:55:43 -0700 Subject: [PATCH 39/59] :recycle: chore: Make port configurable :bug: fix: Fix port env var --- indexer/indexer.toml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/indexer/indexer.toml b/indexer/indexer.toml index c164a5abb..dbf2b65af 100644 --- a/indexer/indexer.toml +++ b/indexer/indexer.toml @@ -22,11 +22,15 @@ l1-rpc = "${INDEXER_RPC_URL_L1}" l2-rpc = "${INDEXER_RPC_URL_L2}" [db] -host = "postgres" -port = 5432 -user = "db_username" -password = "db_password" -name = "db_name" +host = "$INDEXER_DB_HOST" +# this port may be problematic once we depoly +# the DATABASE_URL looks like this for previous services and didn't include a port +# DATABASE_URL="postgresql://${INDEXER_DB_USER}:${INDEXER_DB_PASS}@localhost/${INDEXER_DB_NAME}?host=${INDEXER_DB_HOST}" +# If not problematic delete these comments +port = $INDEXER_DB_PORT +user = "$INDEXER_DB_USER" +password = "$INDEXER_DB_PASS" +name = "$INDEXER_DB_NAME" [http] host = "127.0.0.1" From 896d5160502bf65821a69d6c37d4939807c2b21f Mon Sep 17 00:00:00 2001 From: Will Cory Date: Thu, 31 Aug 2023 20:00:42 -0700 Subject: [PATCH 40/59] :wrench: chore: update schema.prisma --- indexer/ui/schema.prisma | 147 +++++++++++++++++++-------------------- 1 file changed, 73 insertions(+), 74 deletions(-) diff --git a/indexer/ui/schema.prisma b/indexer/ui/schema.prisma index a48b3ce04..3dac38b16 100644 --- a/indexer/ui/schema.prisma +++ b/indexer/ui/schema.prisma @@ -4,35 +4,34 @@ generator client { datasource db { provider = "postgresql" - url = env("DATABASE_URL") + url = "postgresql://db_username:db_password@localhost:5434/db_name" } model l1_bridged_tokens { - address String @id @db.VarChar - bridge_address String @db.VarChar - l2_token_address String @db.VarChar - name String @db.VarChar - symbol String @db.VarChar - decimals Int - l2_bridged_tokens l2_bridged_tokens[] + address String @id @db.VarChar + bridge_address String @db.VarChar + name String @db.VarChar + symbol String @db.VarChar + decimals Int + l2_bridged_tokens l2_bridged_tokens[] } model l2_bridged_tokens { - address String @id @db.VarChar - bridge_address String @db.VarChar - l1_token_address String? @db.VarChar - name String @db.VarChar - symbol String @db.VarChar - decimals Int - l1_bridged_tokens l1_bridged_tokens? @relation(fields: [l1_token_address], references: [address], onDelete: NoAction, onUpdate: NoAction) + address String @id @db.VarChar + bridge_address String @db.VarChar + l1_token_address String? @db.VarChar + name String @db.VarChar + symbol String @db.VarChar + decimals Int + l1_bridged_tokens l1_bridged_tokens? @relation(fields: [l1_token_address], references: [address], onDelete: Cascade, onUpdate: NoAction) } /// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. model l1_block_headers { hash String @id @db.VarChar - parent_hash String @db.VarChar - number Decimal @db.Decimal - timestamp Int + parent_hash String @unique @db.VarChar + number Decimal @unique @db.Decimal + timestamp Int @unique rlp_bytes String @db.VarChar l1_contract_events l1_contract_events[] } @@ -40,7 +39,7 @@ model l1_block_headers { /// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. model l1_bridge_deposits { transaction_source_hash String @id @db.VarChar - cross_domain_message_hash String? @unique @db.VarChar + cross_domain_message_hash String @unique @db.VarChar from_address String @db.VarChar to_address String @db.VarChar local_token_address String @db.VarChar @@ -48,8 +47,8 @@ model l1_bridge_deposits { amount Decimal @db.Decimal data String @db.VarChar timestamp Int - l1_bridge_messages l1_bridge_messages? @relation(fields: [cross_domain_message_hash], references: [message_hash], onDelete: NoAction, onUpdate: NoAction) - l1_transaction_deposits l1_transaction_deposits @relation(fields: [transaction_source_hash], references: [source_hash], onDelete: NoAction, onUpdate: NoAction) + l1_bridge_messages l1_bridge_messages @relation(fields: [cross_domain_message_hash], references: [message_hash], onDelete: Cascade, onUpdate: NoAction) + l1_transaction_deposits l1_transaction_deposits @relation(fields: [transaction_source_hash], references: [source_hash], onDelete: Cascade, onUpdate: NoAction) } /// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. @@ -66,36 +65,36 @@ model l1_bridge_messages { data String @db.VarChar timestamp Int l1_bridge_deposits l1_bridge_deposits? - l2_contract_events l2_contract_events? @relation(fields: [relayed_message_event_guid], references: [guid], onDelete: NoAction, onUpdate: NoAction) - l1_contract_events l1_contract_events @relation(fields: [sent_message_event_guid], references: [guid], onDelete: NoAction, onUpdate: NoAction) - l1_transaction_deposits l1_transaction_deposits @relation(fields: [transaction_source_hash], references: [source_hash], onDelete: NoAction, onUpdate: NoAction) + l2_contract_events l2_contract_events? @relation(fields: [relayed_message_event_guid], references: [guid], onDelete: Cascade, onUpdate: NoAction) + l1_contract_events l1_contract_events @relation(fields: [sent_message_event_guid], references: [guid], onDelete: Cascade, onUpdate: NoAction) + l1_transaction_deposits l1_transaction_deposits @relation(fields: [transaction_source_hash], references: [source_hash], onDelete: Cascade, onUpdate: NoAction) } /// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. model l1_contract_events { - guid String @id @db.VarChar - block_hash String @db.VarChar - contract_address String @db.VarChar - transaction_hash String @db.VarChar + guid String @id @db.VarChar + block_hash String @db.VarChar + contract_address String @db.VarChar + transaction_hash String @db.VarChar log_index Int - event_signature String @db.VarChar + event_signature String @db.VarChar timestamp Int - rlp_bytes String @db.VarChar + rlp_bytes String @db.VarChar l1_bridge_messages l1_bridge_messages? - l1_block_headers l1_block_headers @relation(fields: [block_hash], references: [hash], onDelete: NoAction, onUpdate: NoAction) - l1_transaction_deposits l1_transaction_deposits[] + l1_block_headers l1_block_headers @relation(fields: [block_hash], references: [hash], onDelete: Cascade, onUpdate: NoAction) + l1_transaction_deposits l1_transaction_deposits? l2_bridge_messages l2_bridge_messages? - l2_transaction_withdrawals_l2_transaction_withdrawals_finalized_l1_event_guidTol1_contract_events l2_transaction_withdrawals[] @relation("l2_transaction_withdrawals_finalized_l1_event_guidTol1_contract_events") - l2_transaction_withdrawals_l2_transaction_withdrawals_proven_l1_event_guidTol1_contract_events l2_transaction_withdrawals[] @relation("l2_transaction_withdrawals_proven_l1_event_guidTol1_contract_events") - legacy_state_batches legacy_state_batches[] - output_proposals output_proposals[] + l2_transaction_withdrawals_l2_transaction_withdrawals_finalized_l1_event_guidTol1_contract_events l2_transaction_withdrawals? @relation("l2_transaction_withdrawals_finalized_l1_event_guidTol1_contract_events") + l2_transaction_withdrawals_l2_transaction_withdrawals_proven_l1_event_guidTol1_contract_events l2_transaction_withdrawals? @relation("l2_transaction_withdrawals_proven_l1_event_guidTol1_contract_events") + legacy_state_batches legacy_state_batches? + output_proposals output_proposals? } /// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. model l1_transaction_deposits { source_hash String @id @db.VarChar - l2_transaction_hash String @db.VarChar - initiated_l1_event_guid String @db.VarChar + l2_transaction_hash String @unique @db.VarChar + initiated_l1_event_guid String @unique @db.VarChar from_address String @db.VarChar to_address String @db.VarChar amount Decimal @db.Decimal @@ -104,15 +103,15 @@ model l1_transaction_deposits { timestamp Int l1_bridge_deposits l1_bridge_deposits? l1_bridge_messages l1_bridge_messages? - l1_contract_events l1_contract_events @relation(fields: [initiated_l1_event_guid], references: [guid], onDelete: NoAction, onUpdate: NoAction) + l1_contract_events l1_contract_events @relation(fields: [initiated_l1_event_guid], references: [guid], onDelete: Cascade, onUpdate: NoAction) } /// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. model l2_block_headers { hash String @id @db.VarChar - parent_hash String @db.VarChar - number Decimal @db.Decimal - timestamp Int + parent_hash String @unique @db.VarChar + number Decimal @unique @db.Decimal + timestamp Int @unique rlp_bytes String @db.VarChar l2_contract_events l2_contract_events[] } @@ -130,16 +129,16 @@ model l2_bridge_messages { gas_limit Decimal @db.Decimal data String @db.VarChar timestamp Int - l1_contract_events l1_contract_events? @relation(fields: [relayed_message_event_guid], references: [guid], onDelete: NoAction, onUpdate: NoAction) - l2_contract_events l2_contract_events @relation(fields: [sent_message_event_guid], references: [guid], onDelete: NoAction, onUpdate: NoAction) - l2_transaction_withdrawals l2_transaction_withdrawals @relation(fields: [transaction_withdrawal_hash], references: [withdrawal_hash], onDelete: NoAction, onUpdate: NoAction) + l1_contract_events l1_contract_events? @relation(fields: [relayed_message_event_guid], references: [guid], onDelete: Cascade, onUpdate: NoAction) + l2_contract_events l2_contract_events @relation(fields: [sent_message_event_guid], references: [guid], onDelete: Cascade, onUpdate: NoAction) + l2_transaction_withdrawals l2_transaction_withdrawals @relation(fields: [transaction_withdrawal_hash], references: [withdrawal_hash], onDelete: Cascade, onUpdate: NoAction) l2_bridge_withdrawals l2_bridge_withdrawals? } /// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. model l2_bridge_withdrawals { transaction_withdrawal_hash String @id @db.VarChar - cross_domain_message_hash String? @unique @db.VarChar + cross_domain_message_hash String @unique @db.VarChar from_address String @db.VarChar to_address String @db.VarChar local_token_address String @db.VarChar @@ -147,34 +146,34 @@ model l2_bridge_withdrawals { amount Decimal @db.Decimal data String @db.VarChar timestamp Int - l2_bridge_messages l2_bridge_messages? @relation(fields: [cross_domain_message_hash], references: [message_hash], onDelete: NoAction, onUpdate: NoAction) - l2_transaction_withdrawals l2_transaction_withdrawals @relation(fields: [transaction_withdrawal_hash], references: [withdrawal_hash], onDelete: NoAction, onUpdate: NoAction) + l2_bridge_messages l2_bridge_messages @relation(fields: [cross_domain_message_hash], references: [message_hash], onDelete: Cascade, onUpdate: NoAction) + l2_transaction_withdrawals l2_transaction_withdrawals @relation(fields: [transaction_withdrawal_hash], references: [withdrawal_hash], onDelete: Cascade, onUpdate: NoAction) } /// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. model l2_contract_events { - guid String @id @db.VarChar - block_hash String @db.VarChar - contract_address String @db.VarChar - transaction_hash String @db.VarChar + guid String @id @db.VarChar + block_hash String @db.VarChar + contract_address String @db.VarChar + transaction_hash String @db.VarChar log_index Int - event_signature String @db.VarChar + event_signature String @db.VarChar timestamp Int - rlp_bytes String @db.VarChar + rlp_bytes String @db.VarChar l1_bridge_messages l1_bridge_messages? l2_bridge_messages l2_bridge_messages? - l2_block_headers l2_block_headers @relation(fields: [block_hash], references: [hash], onDelete: NoAction, onUpdate: NoAction) - l2_transaction_withdrawals l2_transaction_withdrawals[] + l2_block_headers l2_block_headers @relation(fields: [block_hash], references: [hash], onDelete: Cascade, onUpdate: NoAction) + l2_transaction_withdrawals l2_transaction_withdrawals? } /// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info. model l2_transaction_withdrawals { withdrawal_hash String @id @db.VarChar - initiated_l2_event_guid String @db.VarChar - proven_l1_event_guid String? @db.VarChar - finalized_l1_event_guid String? @db.VarChar + nonce Decimal @unique @db.Decimal + initiated_l2_event_guid String @unique @db.VarChar + proven_l1_event_guid String? @unique @db.VarChar + finalized_l1_event_guid String? @unique @db.VarChar succeeded Boolean? - nonce Decimal? @unique @db.Decimal from_address String @db.VarChar to_address String @db.VarChar amount Decimal @db.Decimal @@ -183,24 +182,24 @@ model l2_transaction_withdrawals { timestamp Int l2_bridge_messages l2_bridge_messages? l2_bridge_withdrawals l2_bridge_withdrawals? - l1_contract_events_l2_transaction_withdrawals_finalized_l1_event_guidTol1_contract_events l1_contract_events? @relation("l2_transaction_withdrawals_finalized_l1_event_guidTol1_contract_events", fields: [finalized_l1_event_guid], references: [guid], onDelete: NoAction, onUpdate: NoAction) - l2_contract_events l2_contract_events @relation(fields: [initiated_l2_event_guid], references: [guid], onDelete: NoAction, onUpdate: NoAction) - l1_contract_events_l2_transaction_withdrawals_proven_l1_event_guidTol1_contract_events l1_contract_events? @relation("l2_transaction_withdrawals_proven_l1_event_guidTol1_contract_events", fields: [proven_l1_event_guid], references: [guid], onDelete: NoAction, onUpdate: NoAction) + l1_contract_events_l2_transaction_withdrawals_finalized_l1_event_guidTol1_contract_events l1_contract_events? @relation("l2_transaction_withdrawals_finalized_l1_event_guidTol1_contract_events", fields: [finalized_l1_event_guid], references: [guid], onDelete: Cascade, onUpdate: NoAction) + l2_contract_events l2_contract_events @relation(fields: [initiated_l2_event_guid], references: [guid], onDelete: Cascade, onUpdate: NoAction) + l1_contract_events_l2_transaction_withdrawals_proven_l1_event_guidTol1_contract_events l1_contract_events? @relation("l2_transaction_withdrawals_proven_l1_event_guidTol1_contract_events", fields: [proven_l1_event_guid], references: [guid], onDelete: Cascade, onUpdate: NoAction) } model legacy_state_batches { - index Int @id - root String @db.VarChar - size Int - prev_total Int - l1_contract_event_guid String? @db.VarChar - l1_contract_events l1_contract_events? @relation(fields: [l1_contract_event_guid], references: [guid], onDelete: NoAction, onUpdate: NoAction) + index Int @id + root String @unique @db.VarChar + size Int + prev_total Int + state_batch_appended_guid String @unique @db.VarChar + l1_contract_events l1_contract_events @relation(fields: [state_batch_appended_guid], references: [guid], onDelete: Cascade, onUpdate: NoAction) } model output_proposals { - output_root String @id @db.VarChar - l2_output_index Decimal @db.Decimal - l2_block_number Decimal @db.Decimal - l1_contract_event_guid String? @db.VarChar - l1_contract_events l1_contract_events? @relation(fields: [l1_contract_event_guid], references: [guid], onDelete: NoAction, onUpdate: NoAction) + output_root String @id @db.VarChar + l2_output_index Decimal @unique @db.Decimal + l2_block_number Decimal @unique @db.Decimal + output_proposed_guid String @unique @db.VarChar + l1_contract_events l1_contract_events @relation(fields: [output_proposed_guid], references: [guid], onDelete: Cascade, onUpdate: NoAction) } From 2012b3b0aa3c70a2d262820273edff73bbf28bf8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 07:20:49 +0000 Subject: [PATCH 41/59] build(deps-dev): bump @vitest/coverage-istanbul from 0.34.1 to 0.34.3 Bumps [@vitest/coverage-istanbul](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-istanbul) from 0.34.1 to 0.34.3. - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Commits](https://github.com/vitest-dev/vitest/commits/v0.34.3/packages/coverage-istanbul) --- updated-dependencies: - dependency-name: "@vitest/coverage-istanbul" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pnpm-lock.yaml | 223 ++++--------------------------------------------- 1 file changed, 17 insertions(+), 206 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a93b961cc..28da8cd69 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -604,13 +604,6 @@ packages: '@babel/highlight': 7.22.10 chalk: 2.4.2 - /@babel/code-frame@7.22.5: - resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.22.10 - dev: true - /@babel/compat-data@7.22.9: resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==} engines: {node: '>=6.9.0'} @@ -639,29 +632,6 @@ packages: - supports-color dev: true - /@babel/core@7.22.9: - resolution: {integrity: sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.22.10 - '@babel/generator': 7.22.9 - '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) - '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.9) - '@babel/helpers': 7.22.6 - '@babel/parser': 7.22.7 - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.8 - '@babel/types': 7.22.5 - convert-source-map: 1.9.0 - debug: 4.3.4(supports-color@8.1.1) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/eslint-parser@7.22.15(@babel/core@7.22.10)(eslint@8.47.0): resolution: {integrity: sha512-yc8OOBIQk1EcRrpizuARSQS0TWAcOMpEJ1aafhNznaeYkeL+OhqnDObGFylB8ka8VFF/sZc+S4RzHyO+3LjQxg==} engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} @@ -686,26 +656,6 @@ packages: jsesc: 2.5.2 dev: true - /@babel/generator@7.22.5: - resolution: {integrity: sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.5 - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.19 - jsesc: 2.5.2 - dev: true - - /@babel/generator@7.22.9: - resolution: {integrity: sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.5 - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.19 - jsesc: 2.5.2 - dev: true - /@babel/helper-compilation-targets@7.22.10: resolution: {integrity: sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==} engines: {node: '>=6.9.0'} @@ -717,65 +667,31 @@ packages: semver: 6.3.1 dev: true - /@babel/helper-compilation-targets@7.22.9(@babel/core@7.22.9): - resolution: {integrity: sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.22.9 - '@babel/core': 7.22.9 - '@babel/helper-validator-option': 7.22.5 - browserslist: 4.21.9 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-environment-visitor@7.18.2: - resolution: {integrity: sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==} - engines: {node: '>=6.9.0'} - dev: true - /@babel/helper-environment-visitor@7.22.5: resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==} engines: {node: '>=6.9.0'} dev: true - /@babel/helper-function-name@7.17.9: - resolution: {integrity: sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.22.5 - '@babel/types': 7.22.5 - dev: true - /@babel/helper-function-name@7.22.5: resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==} engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.22.5 - '@babel/types': 7.22.5 - dev: true - - /@babel/helper-hoist-variables@7.16.7: - resolution: {integrity: sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.5 + '@babel/types': 7.22.10 dev: true /@babel/helper-hoist-variables@7.22.5: resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.22.5 + '@babel/types': 7.22.10 dev: true /@babel/helper-module-imports@7.22.5: resolution: {integrity: sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.22.5 + '@babel/types': 7.22.10 dev: true /@babel/helper-module-transforms@7.22.9(@babel/core@7.22.10): @@ -792,39 +708,18 @@ packages: '@babel/helper-validator-identifier': 7.22.5 dev: true - /@babel/helper-module-transforms@7.22.9(@babel/core@7.22.9): - resolution: {integrity: sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-module-imports': 7.22.5 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.5 - dev: true - /@babel/helper-simple-access@7.22.5: resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.22.5 - dev: true - - /@babel/helper-split-export-declaration@7.16.7: - resolution: {integrity: sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.5 + '@babel/types': 7.22.10 dev: true /@babel/helper-split-export-declaration@7.22.6: resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.22.5 + '@babel/types': 7.22.10 dev: true /@babel/helper-string-parser@7.22.5: @@ -857,17 +752,6 @@ packages: - supports-color dev: true - /@babel/helpers@7.22.6: - resolution: {integrity: sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.8 - '@babel/types': 7.22.5 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/highlight@7.22.10: resolution: {integrity: sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==} engines: {node: '>=6.9.0'} @@ -881,7 +765,7 @@ packages: engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.22.5 + '@babel/types': 7.22.10 dev: true /@babel/parser@7.22.10: @@ -892,22 +776,6 @@ packages: '@babel/types': 7.22.10 dev: true - /@babel/parser@7.22.5: - resolution: {integrity: sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.22.5 - dev: true - - /@babel/parser@7.22.7: - resolution: {integrity: sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.22.5 - dev: true - /@babel/runtime@7.20.7: resolution: {integrity: sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==} engines: {node: '>=6.9.0'} @@ -926,31 +794,13 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.22.10 - '@babel/parser': 7.22.7 - '@babel/types': 7.22.5 + '@babel/parser': 7.22.10 + '@babel/types': 7.22.10 dev: true /@babel/traverse@7.18.2: resolution: {integrity: sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.5 - '@babel/generator': 7.22.5 - '@babel/helper-environment-visitor': 7.18.2 - '@babel/helper-function-name': 7.17.9 - '@babel/helper-hoist-variables': 7.16.7 - '@babel/helper-split-export-declaration': 7.16.7 - '@babel/parser': 7.22.5 - '@babel/types': 7.22.5 - debug: 4.3.4(supports-color@8.1.1) - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/traverse@7.22.10: - resolution: {integrity: sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==} - engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.22.10 '@babel/generator': 7.22.10 @@ -966,18 +816,18 @@ packages: - supports-color dev: true - /@babel/traverse@7.22.8: - resolution: {integrity: sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==} + /@babel/traverse@7.22.10: + resolution: {integrity: sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==} engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.22.10 - '@babel/generator': 7.22.9 + '@babel/generator': 7.22.10 '@babel/helper-environment-visitor': 7.22.5 '@babel/helper-function-name': 7.22.5 '@babel/helper-hoist-variables': 7.22.5 '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.22.7 - '@babel/types': 7.22.5 + '@babel/parser': 7.22.10 + '@babel/types': 7.22.10 debug: 4.3.4(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: @@ -993,15 +843,6 @@ packages: to-fast-properties: 2.0.0 dev: true - /@babel/types@7.22.5: - resolution: {integrity: sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.22.5 - '@babel/helper-validator-identifier': 7.22.5 - to-fast-properties: 2.0.0 - dev: true - /@changesets/apply-release-plan@6.1.3: resolution: {integrity: sha512-ECDNeoc3nfeAe1jqJb5aFQX7CqzQhD2klXRez2JDb/aVpGUbX673HgKrnrgJRuQR/9f2TtLoYIzrGB9qwD77mg==} dependencies: @@ -4578,7 +4419,7 @@ packages: /@vue/compiler-core@3.2.36: resolution: {integrity: sha512-bbyZM5hvBicv0PW3KUfVi+x3ylHnfKG7DOn5wM+f2OztTzTjLEyBb/5yrarIYpmnGitVGbjZqDbODyW4iK8hqw==} dependencies: - '@babel/parser': 7.22.5 + '@babel/parser': 7.22.10 '@vue/shared': 3.2.36 estree-walker: 2.0.2 source-map: 0.6.1 @@ -4594,7 +4435,7 @@ packages: /@vue/compiler-sfc@3.2.36: resolution: {integrity: sha512-AvGb4bTj4W8uQ4BqaSxo7UwTEqX5utdRSMyHy58OragWlt8nEACQ9mIeQh3K4di4/SX+41+pJrLIY01lHAOFOA==} dependencies: - '@babel/parser': 7.22.5 + '@babel/parser': 7.22.10 '@vue/compiler-core': 3.2.36 '@vue/compiler-dom': 3.2.36 '@vue/compiler-ssr': 3.2.36 @@ -4616,7 +4457,7 @@ packages: /@vue/reactivity-transform@3.2.36: resolution: {integrity: sha512-Jk5o2BhpODC9XTA7o4EL8hSJ4JyrFWErLtClG3NH8wDS7ri9jBDWxI7/549T7JY9uilKsaNM+4pJASLj5dtRwA==} dependencies: - '@babel/parser': 7.22.5 + '@babel/parser': 7.22.10 '@vue/compiler-core': 3.2.36 '@vue/shared': 3.2.36 estree-walker: 2.0.2 @@ -6105,17 +5946,6 @@ packages: update-browserslist-db: 1.0.11(browserslist@4.21.10) dev: true - /browserslist@4.21.9: - resolution: {integrity: sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001517 - electron-to-chromium: 1.4.468 - node-releases: 2.0.13 - update-browserslist-db: 1.0.11(browserslist@4.21.9) - dev: true - /bs58@4.0.1: resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} dependencies: @@ -6302,10 +6132,6 @@ packages: engines: {node: '>=10'} dev: true - /caniuse-lite@1.0.30001517: - resolution: {integrity: sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==} - dev: true - /caniuse-lite@1.0.30001520: resolution: {integrity: sha512-tahF5O9EiiTzwTUqAeFjIZbn4Dnqxzz7ktrgGlMYNLH43Ul26IgTMH/zvL3DG0lZxBYnlT04axvInszUsZULdA==} dev: true @@ -7455,10 +7281,6 @@ packages: jake: 10.8.7 dev: true - /electron-to-chromium@1.4.468: - resolution: {integrity: sha512-6M1qyhaJOt7rQtNti1lBA0GwclPH+oKCmsra/hkcWs5INLxfXXD/dtdnaKUYQu/pjOBP/8Osoe4mAcNvvzoFag==} - dev: true - /electron-to-chromium@1.4.491: resolution: {integrity: sha512-ZzPqGKghdVzlQJ+qpfE+r6EB321zed7e5JsvHIlMM4zPFF8okXUkF5Of7h7F3l3cltPL0rG7YVmlp5Qro7RQLA==} dev: true @@ -10394,7 +10216,7 @@ packages: resolution: {integrity: sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==} engines: {node: '>=8'} dependencies: - '@babel/core': 7.22.9 + '@babel/core': 7.22.10 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.0 semver: 6.3.1 @@ -15823,17 +15645,6 @@ packages: picocolors: 1.0.0 dev: true - /update-browserslist-db@1.0.11(browserslist@4.21.9): - resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.21.9 - escalade: 3.1.1 - picocolors: 1.0.0 - dev: true - /update-section@0.3.3: resolution: {integrity: sha512-BpRZMZpgXLuTiKeiu7kK0nIPwGdyrqrs6EDSaXtjD/aQ2T+qVo9a5hRC3HN3iJjCMxNT/VxoLGQ7E/OzE5ucnw==} dev: true From be4a6477f00f49845066fa9b3e15cb7a79b50dfa Mon Sep 17 00:00:00 2001 From: Andreas Bigger Date: Wed, 6 Sep 2023 12:21:36 -0400 Subject: [PATCH 42/59] Fixes small markdown header. --- docs/fault-proof-alpha/manual.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/fault-proof-alpha/manual.md b/docs/fault-proof-alpha/manual.md index bb59ae712..570f1fa97 100644 --- a/docs/fault-proof-alpha/manual.md +++ b/docs/fault-proof-alpha/manual.md @@ -1,6 +1,6 @@ ## Manual Fault Proof Interactions -## Creating a Game +### Creating a Game The process of disputing an output root starts by creating a new dispute game. There are conceptually three key inputs required for a dispute game: @@ -48,7 +48,7 @@ newly created dispute game. The helper script, [create_game.sh](../../op-challenger#create_gamesh) can be used to easily create a new dispute game and also acts as an example of using `cast` to manually create a game. -## Performing Moves +### Performing Moves The dispute game progresses by actors countering existing claims via either the `attack` or `defend` methods in the `FaultDisputeGame` contract. Note that only `attack` can be used to counter the root claim. In both cases, there are @@ -60,7 +60,7 @@ two inputs required: The helper script, [move.sh](../../op-challenger#movesh), can be used to easily perform moves and also acts as an example of using `cast` to manually call `attack` and `defend`. -## Performing Steps +### Performing Steps Attacking or defending are teh only available actions before the maximum depth of the game is reached. To counter claims at the maximum depth, a step must be performed instead. Calling the `step` method in the `FaultDisputeGame` contract @@ -89,7 +89,7 @@ The `step` function will revert with `ValidStep()` if the cannon execution prove countered is correct. As a result, claims at the maximum game depth can only be countered by a valid execution of the single instruction in cannon running on-chain. -### Populating the Pre-image Oracle +#### Populating the Pre-image Oracle When the instruction to be executed as part of a `step` call reads from some pre-image data, that data must be loaded into the pre-image oracle prior to calling `step`. @@ -98,7 +98,7 @@ the `FaultDisputeGame` contract by calling the `addLocalData` function. For [global keccak256 keys](../../specs/fault-proof.md#type-2-global-keccak256-key), the data should be added directly to the pre-image oracle contract. -## Resolving a Game +### Resolving a Game The final action required for a game is to resolve it by calling the `resolve` method in the `FaultDisputeGame` contract. This can only be done once the clock of the left-most uncontested claim’s parent has expired. A game can only From d35ffaee3386e0acb45bac8d2e549eb02de1f208 Mon Sep 17 00:00:00 2001 From: Hamdi Allam Date: Wed, 6 Sep 2023 12:24:10 -0400 Subject: [PATCH 43/59] small bugfix --- indexer/processors/bridge/l1_bridge_processor.go | 14 +++++++------- indexer/processors/bridge/l2_bridge_processor.go | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/indexer/processors/bridge/l1_bridge_processor.go b/indexer/processors/bridge/l1_bridge_processor.go index 8d82719b8..28de76008 100644 --- a/indexer/processors/bridge/l1_bridge_processor.go +++ b/indexer/processors/bridge/l1_bridge_processor.go @@ -51,7 +51,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, chainConfig if err != nil { return err } - if len(crossDomainSentMessages) > len(transactionDeposits) { + if len(crossDomainSentMessages) < len(transactionDeposits) { return fmt.Errorf("missing transaction deposit for each cross-domain message. deposits: %d, messages: %d", len(transactionDeposits), len(crossDomainSentMessages)) } @@ -64,7 +64,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, chainConfig // extract the deposit hash from the previous TransactionDepositedEvent portalDeposit, ok := portalDeposits[logKey{sentMessage.Event.BlockHash, sentMessage.Event.LogIndex - 1}] if !ok { - return fmt.Errorf("missing expected preceding TransactionDeposit for SentMessage. tx_hash = %s", sentMessage.Event.TransactionHash) + return fmt.Errorf("expected TransactionDeposit preceding SentMessage event. tx_hash = %s", sentMessage.Event.TransactionHash) } l1BridgeMessages[i] = database.L1BridgeMessage{TransactionSourceHash: portalDeposit.DepositTx.SourceHash, BridgeMessage: sentMessage.BridgeMessage} @@ -82,7 +82,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, chainConfig if err != nil { return err } - if len(initiatedBridges) > len(crossDomainSentMessages) { + if len(initiatedBridges) < len(crossDomainSentMessages) { return fmt.Errorf("missing cross-domain message for each initiated bridge event. messages: %d, bridges: %d", len(crossDomainSentMessages), len(initiatedBridges)) } @@ -93,11 +93,11 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, chainConfig // extract the cross domain message hash & deposit source hash from the following events portalDeposit, ok := portalDeposits[logKey{initiatedBridge.Event.BlockHash, initiatedBridge.Event.LogIndex + 1}] if !ok { - return fmt.Errorf("missing expected following TransactionDeposit for BridgeInitiated. tx_hash = %s", initiatedBridge.Event.TransactionHash) + return fmt.Errorf("expected TransactionDeposit following BridgeInitiated event. tx_hash = %s", initiatedBridge.Event.TransactionHash) } sentMessage, ok := sentMessages[logKey{initiatedBridge.Event.BlockHash, initiatedBridge.Event.LogIndex + 2}] if !ok { - return fmt.Errorf("missing expected following SentMessage for BridgeInitiated. tx_hash = %s", initiatedBridge.Event.TransactionHash) + return fmt.Errorf("expected SentMessage following TransactionDeposit event. tx_hash = %s", initiatedBridge.Event.TransactionHash) } initiatedBridge.BridgeTransfer.CrossDomainMessageHash = &sentMessage.BridgeMessage.MessageHash @@ -205,7 +205,7 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, chainConfig if err != nil { return err } - if len(finalizedBridges) > len(crossDomainRelayedMessages) { + if len(finalizedBridges) < len(crossDomainRelayedMessages) { return fmt.Errorf("missing cross-domain message for each finalized bridge event. messages: %d, bridges: %d", len(crossDomainRelayedMessages), len(finalizedBridges)) } @@ -215,7 +215,7 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, chainConfig finalizedBridge := finalizedBridges[i] relayedMessage, ok := relayedMessages[logKey{finalizedBridge.Event.BlockHash, finalizedBridge.Event.LogIndex + 1}] if !ok { - return fmt.Errorf("missing following RelayedMessage for BridgeFinalized event. tx_hash = %s", finalizedBridge.Event.TransactionHash) + return fmt.Errorf("expected RelayedMessage following BridgeFinalized event. tx_hash = %s", finalizedBridge.Event.TransactionHash) } // Since the message hash is computed from the relayed message, this ensures the deposit fields must match. For good measure, diff --git a/indexer/processors/bridge/l2_bridge_processor.go b/indexer/processors/bridge/l2_bridge_processor.go index 803f3a2fc..7a3ee47df 100644 --- a/indexer/processors/bridge/l2_bridge_processor.go +++ b/indexer/processors/bridge/l2_bridge_processor.go @@ -50,7 +50,7 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, fromHeight if err != nil { return err } - if len(crossDomainSentMessages) > len(messagesPassed) { + if len(crossDomainSentMessages) < len(messagesPassed) { return fmt.Errorf("missing L2ToL1MP withdrawal for each cross-domain message. withdrawals: %d, messages: %d", len(messagesPassed), len(crossDomainSentMessages)) } @@ -63,7 +63,7 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, fromHeight // extract the withdrawal hash from the previous MessagePassed event messagePassed, ok := messagesPassed[logKey{sentMessage.Event.BlockHash, sentMessage.Event.LogIndex - 1}] if !ok { - return fmt.Errorf("missing expected preceding MessagePassedEvent for SentMessage. tx_hash = %s", sentMessage.Event.TransactionHash) + return fmt.Errorf("expected MessagePassedEvent preceding SentMessage. tx_hash = %s", sentMessage.Event.TransactionHash) } l2BridgeMessages[i] = database.L2BridgeMessage{TransactionWithdrawalHash: messagePassed.WithdrawalHash, BridgeMessage: sentMessage.BridgeMessage} @@ -81,7 +81,7 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, fromHeight if err != nil { return err } - if len(initiatedBridges) > len(crossDomainSentMessages) { + if len(initiatedBridges) < len(crossDomainSentMessages) { return fmt.Errorf("missing cross-domain message for each initiated bridge event. messages: %d, bridges: %d", len(crossDomainSentMessages), len(initiatedBridges)) } @@ -92,11 +92,11 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, fromHeight // extract the cross domain message hash & deposit source hash from the following events messagePassed, ok := messagesPassed[logKey{initiatedBridge.Event.BlockHash, initiatedBridge.Event.LogIndex + 1}] if !ok { - return fmt.Errorf("missing expected following MessagePassed for BridgeInitiated. tx_hash = %s", initiatedBridge.Event.TransactionHash) + return fmt.Errorf("expected MessagePassed following BridgeInitiated event. tx_hash = %s", initiatedBridge.Event.TransactionHash) } sentMessage, ok := sentMessages[logKey{initiatedBridge.Event.BlockHash, initiatedBridge.Event.LogIndex + 2}] if !ok { - return fmt.Errorf("missing expected following SentMessage for BridgeInitiated. tx_hash = %s", initiatedBridge.Event.TransactionHash) + return fmt.Errorf("expected SentMessage following MessagePassed event. tx_hash = %s", initiatedBridge.Event.TransactionHash) } initiatedBridge.BridgeTransfer.CrossDomainMessageHash = &sentMessage.BridgeMessage.MessageHash @@ -153,7 +153,7 @@ func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, fromHeight if err != nil { return err } - if len(finalizedBridges) > len(crossDomainRelayedMessages) { + if len(finalizedBridges) < len(crossDomainRelayedMessages) { return fmt.Errorf("missing cross-domain message for each finalized bridge event. messages: %d, bridges: %d", len(crossDomainRelayedMessages), len(finalizedBridges)) } @@ -163,7 +163,7 @@ func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, fromHeight finalizedBridge := finalizedBridges[i] relayedMessage, ok := relayedMessages[logKey{finalizedBridge.Event.BlockHash, finalizedBridge.Event.LogIndex + 1}] if !ok { - return fmt.Errorf("missing following RelayedMessage for BridgeFinalized event. tx_hash = %s", finalizedBridge.Event.TransactionHash) + return fmt.Errorf("expected RelayedMessage following BridgeFinalized event. tx_hash = %s", finalizedBridge.Event.TransactionHash) } // Since the message hash is computed from the relayed message, this ensures the withdrawal fields must match. For good measure, From 2fe6842b753aeee959b83b6db6724f2b64f50811 Mon Sep 17 00:00:00 2001 From: Hamdi Allam Date: Wed, 6 Sep 2023 13:19:41 -0400 Subject: [PATCH 44/59] operators were right before --- indexer/processors/bridge/l1_bridge_processor.go | 6 +++--- indexer/processors/bridge/l2_bridge_processor.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/indexer/processors/bridge/l1_bridge_processor.go b/indexer/processors/bridge/l1_bridge_processor.go index 28de76008..7eb39f2a9 100644 --- a/indexer/processors/bridge/l1_bridge_processor.go +++ b/indexer/processors/bridge/l1_bridge_processor.go @@ -51,7 +51,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, chainConfig if err != nil { return err } - if len(crossDomainSentMessages) < len(transactionDeposits) { + if len(crossDomainSentMessages) > len(transactionDeposits) { return fmt.Errorf("missing transaction deposit for each cross-domain message. deposits: %d, messages: %d", len(transactionDeposits), len(crossDomainSentMessages)) } @@ -82,7 +82,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, chainConfig if err != nil { return err } - if len(initiatedBridges) < len(crossDomainSentMessages) { + if len(initiatedBridges) > len(crossDomainSentMessages) { return fmt.Errorf("missing cross-domain message for each initiated bridge event. messages: %d, bridges: %d", len(crossDomainSentMessages), len(initiatedBridges)) } @@ -205,7 +205,7 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, chainConfig if err != nil { return err } - if len(finalizedBridges) < len(crossDomainRelayedMessages) { + if len(finalizedBridges) > len(crossDomainRelayedMessages) { return fmt.Errorf("missing cross-domain message for each finalized bridge event. messages: %d, bridges: %d", len(crossDomainRelayedMessages), len(finalizedBridges)) } diff --git a/indexer/processors/bridge/l2_bridge_processor.go b/indexer/processors/bridge/l2_bridge_processor.go index 7a3ee47df..303d93631 100644 --- a/indexer/processors/bridge/l2_bridge_processor.go +++ b/indexer/processors/bridge/l2_bridge_processor.go @@ -50,7 +50,7 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, fromHeight if err != nil { return err } - if len(crossDomainSentMessages) < len(messagesPassed) { + if len(crossDomainSentMessages) > len(messagesPassed) { return fmt.Errorf("missing L2ToL1MP withdrawal for each cross-domain message. withdrawals: %d, messages: %d", len(messagesPassed), len(crossDomainSentMessages)) } @@ -81,7 +81,7 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, fromHeight if err != nil { return err } - if len(initiatedBridges) < len(crossDomainSentMessages) { + if len(initiatedBridges) > len(crossDomainSentMessages) { return fmt.Errorf("missing cross-domain message for each initiated bridge event. messages: %d, bridges: %d", len(crossDomainSentMessages), len(initiatedBridges)) } @@ -153,7 +153,7 @@ func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, fromHeight if err != nil { return err } - if len(finalizedBridges) < len(crossDomainRelayedMessages) { + if len(finalizedBridges) > len(crossDomainRelayedMessages) { return fmt.Errorf("missing cross-domain message for each finalized bridge event. messages: %d, bridges: %d", len(crossDomainRelayedMessages), len(finalizedBridges)) } From 0784b3b1741d21e37175922fcc9e6e43ad535ace Mon Sep 17 00:00:00 2001 From: Hamdi Allam Date: Wed, 6 Sep 2023 14:33:24 -0400 Subject: [PATCH 45/59] fix bridge startup --- indexer/database/bridge_transactions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indexer/database/bridge_transactions.go b/indexer/database/bridge_transactions.go index c5472cc44..0774fb529 100644 --- a/indexer/database/bridge_transactions.go +++ b/indexer/database/bridge_transactions.go @@ -192,7 +192,7 @@ func (db *bridgeTransactionsDB) L2LatestBlockHeader() (*L2BlockHeader, error) { l2Query := db.gorm.Table("(?) AS l1_deposit_events", l1DepositQuery) l2Query = l2Query.Joins("INNER JOIN l2_block_headers ON l2_block_headers.timestamp = l1_deposit_events.timestamp") - l2Query = l2Query.Select("l2_block_headers.*") + l2Query = l2Query.Order("l2_block_headers.timestamp DESC").Select("l2_block_headers.*") var l2Header L2BlockHeader result := l2Query.Take(&l2Header) From 20f85ba9967aadd06adc5417f4da2de64edc2f84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 19:51:49 +0000 Subject: [PATCH 46/59] build(deps): bump github.com/ethereum/go-ethereum in /op-exporter Bumps [github.com/ethereum/go-ethereum](https://github.com/ethereum/go-ethereum) from 1.10.17 to 1.12.1. - [Release notes](https://github.com/ethereum/go-ethereum/releases) - [Commits](https://github.com/ethereum/go-ethereum/compare/v1.10.17...v1.12.1) --- updated-dependencies: - dependency-name: github.com/ethereum/go-ethereum dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- op-exporter/go.mod | 36 ++-- op-exporter/go.sum | 445 ++++----------------------------------------- 2 files changed, 58 insertions(+), 423 deletions(-) diff --git a/op-exporter/go.mod b/op-exporter/go.mod index cdf20e37e..83c1de764 100644 --- a/op-exporter/go.mod +++ b/op-exporter/go.mod @@ -3,8 +3,8 @@ module github.com/ethereum-optimism/optimism/op-exporter go 1.20 require ( - github.com/ethereum/go-ethereum v1.10.17 - github.com/prometheus/client_golang v1.11.1 + github.com/ethereum/go-ethereum v1.12.1 + github.com/prometheus/client_golang v1.14.0 github.com/sirupsen/logrus v1.7.0 github.com/ybbus/jsonrpc v2.1.2+incompatible gopkg.in/alecthomas/kingpin.v2 v2.2.6 @@ -16,30 +16,30 @@ require ( github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-logr/logr v0.4.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.8 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa // indirect github.com/googleapis/gnostic v0.4.1 // indirect - github.com/json-iterator/go v1.1.11 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/onsi/gomega v1.16.0 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.30.0 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect - golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect - google.golang.org/appengine v1.6.6 // indirect - google.golang.org/protobuf v1.27.1 // 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 + golang.org/x/net v0.10.0 // indirect + golang.org/x/oauth2 v0.3.0 // indirect + golang.org/x/sys v0.9.0 // indirect + golang.org/x/term v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/time v0.3.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/api v0.21.2 // indirect diff --git a/op-exporter/go.sum b/op-exporter/go.sum index 12c1d2f71..72f6b652b 100644 --- a/op-exporter/go.sum +++ b/op-exporter/go.sum @@ -1,43 +1,26 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3/go.mod h1:KLF4gFr6DcKFZwSuH8w8yEK6DpFl3LP5rhdvAb7Yz5I= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= @@ -47,136 +30,54 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= -github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y= -github.com/aws/aws-sdk-go-v2/credentials v1.1.1/go.mod h1:mM2iIjwl7LULWtS6JCACyInboHirisUUdkBPoTHMOUo= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2/go.mod h1:3hGg3PpiEjHnrkrlasTfxFqUsZ2GCk/fMUn4CbKgSkM= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8= -github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4= -github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0= -github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM= -github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= -github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 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/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= -github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= -github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/go-ethereum v1.10.17 h1:XEcumY+qSr1cZQaWsQs5Kck3FHB0V2RiMHPdTBJ+oT8= -github.com/ethereum/go-ethereum v1.10.17/go.mod h1:Lt5WzjM07XlXc95YzrhosmR4J9Ahd6X2wyEV2SvGhk0= +github.com/ethereum/go-ethereum v1.12.1 h1:1kXDPxhLfyySuQYIfRxVBGYuaHdxNNxevA73vjIwsgk= +github.com/ethereum/go-ethereum v1.12.1/go.mod h1:zKetLweqBR8ZS+1O9iJWI8DvmmD2NzD19apjEWDCsnw= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= -github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= -github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= -github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= -github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= -github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -186,8 +87,6 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -205,160 +104,79 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.0.3-0.20220313090229-ca81a64b4204/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY= -github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI= -github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= -github.com/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= -github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= -github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= -github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8= -github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= -github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= -github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= -github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= -github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= -github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -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.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= 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= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -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-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -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= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= -github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= -github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -366,125 +184,52 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= -github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= -github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s= -github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.30.0 h1:JEkYlQnpzrzQFxi6gnukFPdQ+ac82oRhzMcIduJu/Ug= -github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= -github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= +github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= -github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= 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= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= 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/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/ybbus/jsonrpc v2.1.2+incompatible h1:V4mkE9qhbDQ92/MLMIhlhMSbz8jNXdagC3xBR5NDwaQ= github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= @@ -494,7 +239,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -515,11 +259,9 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -529,7 +271,6 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/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= @@ -539,62 +280,37 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8= +golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/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-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/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= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -602,74 +318,46 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.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-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +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-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= -golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -687,7 +375,6 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -695,31 +382,14 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= 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= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= -gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -729,26 +399,19 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -756,36 +419,20 @@ google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -794,12 +441,11 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -807,36 +453,26 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 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/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= -gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= k8s.io/api v0.21.2 h1:vz7DqmRsXTCSa6pNxXwQ1IYeAZgdIsua+DZU+o+SX3Y= k8s.io/api v0.21.2/go.mod h1:Lv6UGJZ1rlMI1qusN8ruAp9PUBFyBwpEHAdG24vIsiU= k8s.io/apimachinery v0.21.2 h1:vezUc/BHqWlQDnZ+XkrpXSmnANSLbpnlpwo0Lhk0gpc= @@ -851,7 +487,6 @@ k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iL k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= From df821cfbfa4fdd80b345a3a7129b56d3d16c9543 Mon Sep 17 00:00:00 2001 From: clabby Date: Wed, 6 Sep 2023 20:21:25 -0400 Subject: [PATCH 47/59] Add `TestStateHash` --- cannon/mipsevm/state_test.go | 47 ++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/cannon/mipsevm/state_test.go b/cannon/mipsevm/state_test.go index 089bd5221..2e866cde5 100644 --- a/cannon/mipsevm/state_test.go +++ b/cannon/mipsevm/state_test.go @@ -82,6 +82,53 @@ func TestState(t *testing.T) { } } +// Run through all permutations of `exited` / `exitCode` and ensure that the +// correct witness, state hash, and VM Status is produced. +func TestStateHash(t *testing.T) { + cases := []struct { + exited bool + exitCode uint8 + }{ + {exited: false, exitCode: 0}, + {exited: false, exitCode: 1}, + {exited: false, exitCode: 2}, + {exited: false, exitCode: 3}, + {exited: true, exitCode: 0}, + {exited: true, exitCode: 1}, + {exited: true, exitCode: 2}, + {exited: true, exitCode: 3}, + } + + exitedOffset := 32*2 + 4*6 + for _, c := range cases { + state := &State{ + Memory: NewMemory(), + Exited: c.exited, + ExitCode: c.exitCode, + } + + actualWitness := state.EncodeWitness() + actualStateHash, err := StateWitness(actualWitness).StateHash() + require.NoError(t, err, "Error hashing witness") + require.Equal(t, len(actualWitness), StateWitnessSize, "Incorrect witness size") + + expectedWitness := make(StateWitness, 226) + memRoot := state.Memory.MerkleRoot() + copy(expectedWitness[:32], memRoot[:]) + expectedWitness[exitedOffset] = c.exitCode + var exited uint8 + if c.exited { + exited = 1 + } + expectedWitness[exitedOffset+1] = uint8(exited) + require.Equal(t, expectedWitness[:], actualWitness[:], "Incorrect witness") + + expectedStateHash := crypto.Keccak256Hash(actualWitness) + expectedStateHash[0] = vmStatus(c.exited, c.exitCode) + require.Equal(t, expectedStateHash, actualStateHash, "Incorrect state hash") + } +} + func TestHello(t *testing.T) { elfProgram, err := elf.Open("../example/bin/hello.elf") require.NoError(t, err, "open ELF file") From 023b3d5e07e68089c80be3c34f6c4e2817dd9c88 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Wed, 6 Sep 2023 10:55:47 +1000 Subject: [PATCH 48/59] op-e2e: Update e2e tests to demonstrate issues with vm status. --- op-e2e/e2eutils/disputegame/game_helper.go | 16 ++++++++-------- op-e2e/e2eutils/disputegame/helper.go | 4 ++++ op-e2e/faultproof_test.go | 1 - 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/op-e2e/e2eutils/disputegame/game_helper.go b/op-e2e/e2eutils/disputegame/game_helper.go index ede4b1450..bd93187a3 100644 --- a/op-e2e/e2eutils/disputegame/game_helper.go +++ b/op-e2e/e2eutils/disputegame/game_helper.go @@ -65,16 +65,16 @@ func (g *FaultGameHelper) MaxDepth(ctx context.Context) int64 { } func (g *FaultGameHelper) waitForClaim(ctx context.Context, errorMsg string, predicate func(claim ContractClaim) bool) { - ctx, cancel := context.WithTimeout(ctx, time.Minute) + timedCtx, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() - err := wait.For(ctx, time.Second, func() (bool, error) { - count, err := g.game.ClaimDataLen(&bind.CallOpts{Context: ctx}) + err := wait.For(timedCtx, time.Second, func() (bool, error) { + count, err := g.game.ClaimDataLen(&bind.CallOpts{Context: timedCtx}) if err != nil { return false, fmt.Errorf("retrieve number of claims: %w", err) } // Search backwards because the new claims are at the end and more likely the ones we want. for i := count.Int64() - 1; i >= 0; i-- { - claimData, err := g.game.ClaimData(&bind.CallOpts{Context: ctx}, big.NewInt(i)) + claimData, err := g.game.ClaimData(&bind.CallOpts{Context: timedCtx}, big.NewInt(i)) if err != nil { return false, fmt.Errorf("retrieve claim %v: %w", i, err) } @@ -127,10 +127,10 @@ func (g *FaultGameHelper) Resolve(ctx context.Context) { func (g *FaultGameHelper) WaitForGameStatus(ctx context.Context, expected Status) { g.t.Logf("Waiting for game %v to have status %v", g.addr, expected) - ctx, cancel := context.WithTimeout(ctx, time.Minute) + timedCtx, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() - err := wait.For(ctx, time.Second, func() (bool, error) { - ctx, cancel := context.WithTimeout(ctx, 30*time.Second) + err := wait.For(timedCtx, time.Second, func() (bool, error) { + ctx, cancel := context.WithTimeout(timedCtx, 30*time.Second) defer cancel() status, err := g.game.Status(&bind.CallOpts{Context: ctx}) if err != nil { @@ -139,7 +139,7 @@ func (g *FaultGameHelper) WaitForGameStatus(ctx context.Context, expected Status g.t.Logf("Game %v has state %v, waiting for state %v", g.addr, Status(status), expected) return expected == Status(status), nil }) - g.require.NoError(err, "wait for game status") + g.require.NoErrorf(err, "wait for game status. Game state: \n%v", g.gameData(ctx)) } func (g *FaultGameHelper) Attack(ctx context.Context, claimIdx int64, claim common.Hash) { diff --git a/op-e2e/e2eutils/disputegame/helper.go b/op-e2e/e2eutils/disputegame/helper.go index c027d63b2..495b3cc61 100644 --- a/op-e2e/e2eutils/disputegame/helper.go +++ b/op-e2e/e2eutils/disputegame/helper.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-chain-ops/deployer" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" @@ -174,6 +175,9 @@ func (h *FactoryHelper) StartCannonGameWithCorrectRoot(ctx context.Context, roll provider := cannon.NewTraceProviderFromInputs(testlog.Logger(h.t, log.LvlInfo).New("role", "CorrectTrace"), metrics.NoopMetrics, cfg, inputs, cfg.Datadir) rootClaim, err := provider.Get(ctx, math.MaxUint64) h.require.NoError(err, "Compute correct root hash") + // Override the VM status to claim the root is invalid + // Otherwise creating the game will fail + rootClaim[0] = mipsevm.VMStatusInvalid game := h.createCannonGame(ctx, l2BlockNumber, l1Head, rootClaim) honestHelper := &HonestHelper{ diff --git a/op-e2e/faultproof_test.go b/op-e2e/faultproof_test.go index e9d6811c3..309e10bdd 100644 --- a/op-e2e/faultproof_test.go +++ b/op-e2e/faultproof_test.go @@ -434,7 +434,6 @@ func setupDisputeGameForInvalidOutputRoot(t *testing.T, outputRoot common.Hash) } func TestCannonChallengeWithCorrectRoot(t *testing.T) { - t.Skip("Not currently handling this case as the correct approach will change when output root bisection is added") InitParallel(t) ctx := context.Background() From 34d694c3f010921ca6afed1189ddccfdaf094d1e Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 7 Sep 2023 13:58:14 +0200 Subject: [PATCH 49/59] op-node: update config-reloading comment Co-authored-by: Adrian Sutton --- op-node/node/node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/op-node/node/node.go b/op-node/node/node.go index e27a1ff52..91aad8121 100644 --- a/op-node/node/node.go +++ b/op-node/node/node.go @@ -199,7 +199,7 @@ func (n *OpNode) initRuntimeConfig(ctx context.Context, cfg *Config) error { return fmt.Errorf("failed to load runtime configuration repeatedly, last error: %w", err) } - // start a background loop, to keep reloading it every 10 minutes + // start a background loop, to keep reloading it at the configured reload interval go func(ctx context.Context, reloadInterval time.Duration) { if reloadInterval <= 0 { n.log.Debug("not running runtime-config reloading background loop") From ce3d79a93dfac2156251b61ed57d3fc6b0ad9c2f Mon Sep 17 00:00:00 2001 From: protolambda Date: Thu, 7 Sep 2023 13:59:45 +0200 Subject: [PATCH 50/59] op-e2e: use wait.ForReceiptOK helper instead of bind.WaitMined --- op-e2e/system_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/op-e2e/system_test.go b/op-e2e/system_test.go index c17148cef..6a20e538e 100644 --- a/op-e2e/system_test.go +++ b/op-e2e/system_test.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-e2e/config" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-node/client" "github.com/ethereum-optimism/optimism/op-node/metrics" rollupNode "github.com/ethereum-optimism/optimism/op-node/node" @@ -1419,9 +1420,8 @@ func TestRuntimeConfigReload(t *testing.T) { require.NoError(t, err) // wait for the change to confirm - receipt, err := bind.WaitMined(context.Background(), l1, tx) + _, err = wait.ForReceiptOK(context.Background(), l1, tx.Hash()) require.NoError(t, err) - require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) // wait for the address to change _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { From 6024d2069410f0d1fce6b9df25c1f6a2cfeea71c Mon Sep 17 00:00:00 2001 From: clabby Date: Thu, 7 Sep 2023 10:28:06 -0400 Subject: [PATCH 51/59] Add `forge clean` to `op-bindings` Makefile --- op-bindings/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/op-bindings/Makefile b/op-bindings/Makefile index 11e7a017a..97b26890b 100644 --- a/op-bindings/Makefile +++ b/op-bindings/Makefile @@ -12,6 +12,7 @@ version: compile: cd $(contracts-dir) && \ + forge clean && \ pnpm build bindings: compile bindings-build From a1a0df721643da915a3b44683bd8a44bc704a9e6 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Fri, 8 Sep 2023 03:34:14 +1000 Subject: [PATCH 52/59] op-e2e: Add call to step that verifies it is reject when matching the original claim. (#7133) --- op-e2e/e2eutils/disputegame/game_helper.go | 13 +++++++++++++ op-e2e/e2eutils/disputegame/honest_helper.go | 15 +++++++++++++++ op-e2e/faultproof_test.go | 6 ++++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/op-e2e/e2eutils/disputegame/game_helper.go b/op-e2e/e2eutils/disputegame/game_helper.go index bd93187a3..ef3e0e6da 100644 --- a/op-e2e/e2eutils/disputegame/game_helper.go +++ b/op-e2e/e2eutils/disputegame/game_helper.go @@ -156,6 +156,19 @@ func (g *FaultGameHelper) Defend(ctx context.Context, claimIdx int64, claim comm g.require.NoError(err, "Defend transaction was not OK") } +type ErrWithData interface { + ErrorData() interface{} +} + +// StepFails attempts to call step and verifies that it fails with ValidStep() +func (g *FaultGameHelper) StepFails(claimIdx int64, isAttack bool, stateData []byte, proof []byte) { + g.t.Logf("Attempting step against claim %v isAttack: %v", claimIdx, isAttack) + _, err := g.game.Step(g.opts, big.NewInt(claimIdx), isAttack, stateData, proof) + errData, ok := err.(ErrWithData) + g.require.Truef(ok, "Error should provide ErrorData method: %v", err) + g.require.Equal("0xfb4e40dd", errData.ErrorData(), "Revert reason should be abi encoded ValidStep()") +} + func (g *FaultGameHelper) gameData(ctx context.Context) string { opts := &bind.CallOpts{Context: ctx} maxDepth := int(g.MaxDepth(ctx)) diff --git a/op-e2e/e2eutils/disputegame/honest_helper.go b/op-e2e/e2eutils/disputegame/honest_helper.go index 6d73728a7..3d3000d8f 100644 --- a/op-e2e/e2eutils/disputegame/honest_helper.go +++ b/op-e2e/e2eutils/disputegame/honest_helper.go @@ -42,3 +42,18 @@ func (h *HonestHelper) Defend(ctx context.Context, claimIdx int64) { h.game.require.NoErrorf(err, "Get correct claim at trace index %v", traceIdx) h.game.Defend(ctx, claimIdx, value) } + +func (h *HonestHelper) StepFails(ctx context.Context, claimIdx int64, isAttack bool) { + ctx, cancel := context.WithTimeout(ctx, 2*time.Minute) + defer cancel() + claim := h.game.getClaim(ctx, claimIdx) + pos := types.NewPositionFromGIndex(claim.Position.Uint64()) + traceIdx := pos.TraceIndex(int(h.game.MaxDepth(ctx))) + if !isAttack { + // If we're defending, then the step will be from the trace to the next one + traceIdx += 1 + } + prestate, proofData, _, err := h.correctTrace.GetStepData(ctx, traceIdx) + h.require.NoError(err, "Get step data") + h.game.StepFails(claimIdx, isAttack, prestate, proofData) +} diff --git a/op-e2e/faultproof_test.go b/op-e2e/faultproof_test.go index 309e10bdd..500a63748 100644 --- a/op-e2e/faultproof_test.go +++ b/op-e2e/faultproof_test.go @@ -360,7 +360,7 @@ func TestCannonProposedOutputRootInvalid(t *testing.T) { InitParallel(t) ctx := context.Background() - sys, l1Client, game, correctTrace := setupDisputeGameForInvalidOutputRoot(t, common.Hash{0xab}) + sys, l1Client, game, correctTrace := setupDisputeGameForInvalidOutputRoot(t, common.Hash{0x01, 0xab}) t.Cleanup(sys.Close) maxDepth := game.MaxDepth(ctx) @@ -385,7 +385,9 @@ func TestCannonProposedOutputRootInvalid(t *testing.T) { game.WaitForClaimAtMaxDepth(ctx, false) // It's on us to call step if we want to win but shouldn't be possible - // Need to add support for this to the helper + correctTrace.StepFails(ctx, maxDepth, true) + // Defending should fail too + correctTrace.StepFails(ctx, maxDepth, false) // Time travel past when the game will be resolvable. sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx)) From ccf977b9d26343fa4618808aaaad8811d89959da Mon Sep 17 00:00:00 2001 From: clabby Date: Thu, 7 Sep 2023 13:38:47 -0400 Subject: [PATCH 53/59] chore: :broom: `foundry.toml` --- packages/contracts-bedrock/foundry.toml | 30 ++++++++++++++++--------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 81c6262b1..f90e6aa4b 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -1,15 +1,20 @@ +################################################################ +# PROFILE: DEFAULT (Local) # +################################################################ + [profile.default] + +# Compilation settings src = 'src' out = 'forge-artifacts' script = 'scripts' optimizer = true optimizer_runs = 999999 - remappings = [ '@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts', '@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts', '@rari-capital/solmate/=lib/solmate', - "@cwia/=lib/clones-with-immutable-args/src", + '@cwia/=lib/clones-with-immutable-args/src', 'forge-std/=lib/forge-std/src', 'ds-test/=lib/forge-std/lib/ds-test/src' ] @@ -17,9 +22,9 @@ extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout'] bytecode_hash = 'none' build_info = true build_info_path = 'artifacts/build-info' -ffi = true -fuzz_runs = 16 +# Test / Script Runner Settings +ffi = true fs_permissions = [ { access='read-write', path='./.resource-metering.csv' }, { access='read-write', path='./deployments/' }, @@ -29,14 +34,19 @@ fs_permissions = [ { access='write', path='./semver-lock.json' }, ] +[fuzz] +runs = 64 + [fmt] line_length=120 -multiline_func_header="all" +multiline_func_header='all' bracket_spacing=true wrap_comments=true -ignore = [ - 'src/vendor/WETH9.sol' -] +ignore = ['src/vendor/WETH9.sol'] + +################################################################ +# PROFILE: CI # +################################################################ -[profile.ci] -fuzz_runs = 512 +[profile.ci.fuzz] +runs = 512 From b8ef1170d573676ac0093f8b260c06cf9b1c24d7 Mon Sep 17 00:00:00 2001 From: Will Cory Date: Thu, 7 Sep 2023 11:50:41 -0700 Subject: [PATCH 54/59] :bug: fix: update prisma schema --- indexer/ui/schema.prisma | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indexer/ui/schema.prisma b/indexer/ui/schema.prisma index 3dac38b16..e3ba4a3c9 100644 --- a/indexer/ui/schema.prisma +++ b/indexer/ui/schema.prisma @@ -4,7 +4,7 @@ generator client { datasource db { provider = "postgresql" - url = "postgresql://db_username:db_password@localhost:5434/db_name" + url = env("DATABASE_URL") } model l1_bridged_tokens { @@ -111,7 +111,7 @@ model l2_block_headers { hash String @id @db.VarChar parent_hash String @unique @db.VarChar number Decimal @unique @db.Decimal - timestamp Int @unique + timestamp Int rlp_bytes String @db.VarChar l2_contract_events l2_contract_events[] } From 3b1a490f190f23a9b91d81a55e755afcc45d674f Mon Sep 17 00:00:00 2001 From: lbeder Date: Thu, 7 Sep 2023 14:53:15 -0400 Subject: [PATCH 55/59] EAS v1.2.0: gas optimizations, minor improvements and fixes, and some typo and NATSPEC fixes (#7094) * Add an index and the schema record data to the Registered event * Gas Optimization: Cache resolver.isPayable() external call * Add extra multiRequest.data.length == 0 validation * Gas Gas Optimization: Cache Revoked event arguments * Make sure to refund the attester/revoker in case of non-last attestation/revocation and where there is no resolver * Gas Optimization: cache loop iteration lengths * Gas Optimization: optimize _resolveAttestation() and _resolveAttestations() * Fix missing Natspec, renaming variables, and incorrect comments * Add explicit deadline to delegated attestation/revocation requests * Provide an option for users to invalidate nonces by increasing their nonces to (higher) new values * Add extra input length validation in multiRevoke and multiAttest functions * Updates sample usage in comments * Capture the payment amount in signatures * Bump version * Emit NonceIncreased event when users increase their nonces * Make delegate attestation deadline inclusive + handle prevent nonce overflow due to user error * Minor fix * Update bindings * Fix lint * Lock semver * Add an index and the schema record data to the Registered event * Gas Optimization: Cache resolver.isPayable() external call * Add extra multiRequest.data.length == 0 validation * Gas Gas Optimization: Cache Revoked event arguments * Make sure to refund the attester/revoker in case of non-last attestation/revocation and where there is no resolver * Gas Optimization: cache loop iteration lengths * Gas Optimization: optimize _resolveAttestation() and _resolveAttestations() * Fix missing Natspec, renaming variables, and incorrect comments * Add explicit deadline to delegated attestation/revocation requests * Provide an option for users to invalidate nonces by increasing their nonces to (higher) new values * Add extra input length validation in multiRevoke and multiAttest functions * Updates sample usage in comments * Capture the payment amount in signatures * Bump version * Emit NonceIncreased event when users increase their nonces * Make delegate attestation deadline inclusive + handle prevent nonce overflow due to user error * Minor fix * Update bindings * Fix lint * Lock semver --- op-bindings/bindings/eas.go | 268 ++++++++++++++---- op-bindings/bindings/eas_more.go | 2 +- op-bindings/bindings/schemaregistry.go | 33 ++- op-bindings/bindings/schemaregistry_more.go | 2 +- packages/contracts-bedrock/semver-lock.json | 4 +- packages/contracts-bedrock/src/EAS/Common.sol | 1 + packages/contracts-bedrock/src/EAS/EAS.sol | 146 ++++++---- packages/contracts-bedrock/src/EAS/IEAS.sol | 24 +- .../src/EAS/ISchemaRegistry.sol | 3 +- .../src/EAS/SchemaRegistry.sol | 6 +- .../src/EAS/eip1271/EIP1271Verifier.sol | 74 +++-- .../src/EAS/resolver/ISchemaResolver.sol | 2 +- .../src/EAS/resolver/SchemaResolver.sol | 15 +- 13 files changed, 415 insertions(+), 165 deletions(-) diff --git a/op-bindings/bindings/eas.go b/op-bindings/bindings/eas.go index 1c94c9ddc..8173faf34 100644 --- a/op-bindings/bindings/eas.go +++ b/op-bindings/bindings/eas.go @@ -64,6 +64,7 @@ type DelegatedAttestationRequest struct { Data AttestationRequestData Signature Signature Attester common.Address + Deadline uint64 } // DelegatedRevocationRequest is an auto generated low-level Go binding around an user-defined struct. @@ -72,6 +73,7 @@ type DelegatedRevocationRequest struct { Data RevocationRequestData Signature Signature Revoker common.Address + Deadline uint64 } // MultiAttestationRequest is an auto generated low-level Go binding around an user-defined struct. @@ -86,6 +88,7 @@ type MultiDelegatedAttestationRequest struct { Data []AttestationRequestData Signatures []Signature Attester common.Address + Deadline uint64 } // MultiDelegatedRevocationRequest is an auto generated low-level Go binding around an user-defined struct. @@ -94,6 +97,7 @@ type MultiDelegatedRevocationRequest struct { Data []RevocationRequestData Signatures []Signature Revoker common.Address + Deadline uint64 } // MultiRevocationRequest is an auto generated low-level Go binding around an user-defined struct. @@ -123,8 +127,8 @@ type Signature struct { // EASMetaData contains all meta data concerning the EAS contract. var EASMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessDenied\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AlreadyRevoked\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AlreadyRevokedOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AlreadyTimestamped\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAttestation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAttestations\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExpirationTime\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOffset\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRevocation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRevocations\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSchema\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidVerifier\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Irrevocable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotPayable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongSchema\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"}],\"name\":\"Attested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"}],\"name\":\"Revoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\"}],\"name\":\"RevokedOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\"}],\"name\":\"Timestamped\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structAttestationRequestData\",\"name\":\"data\",\"type\":\"tuple\"}],\"internalType\":\"structAttestationRequest\",\"name\":\"request\",\"type\":\"tuple\"}],\"name\":\"attest\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structAttestationRequestData\",\"name\":\"data\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structSignature\",\"name\":\"signature\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"}],\"internalType\":\"structDelegatedAttestationRequest\",\"name\":\"delegatedRequest\",\"type\":\"tuple\"}],\"name\":\"attestByDelegation\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAttestTypeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"name\":\"getAttestation\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"time\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revocationTime\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structAttestation\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDomainSeparator\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"name\":\"getRevokeOffchain\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRevokeTypeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSchemaRegistry\",\"outputs\":[{\"internalType\":\"contractISchemaRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"name\":\"getTimestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"name\":\"isAttestationValid\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structAttestationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"internalType\":\"structMultiAttestationRequest[]\",\"name\":\"multiRequests\",\"type\":\"tuple[]\"}],\"name\":\"multiAttest\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structAttestationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structSignature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"}],\"internalType\":\"structMultiDelegatedAttestationRequest[]\",\"name\":\"multiDelegatedRequests\",\"type\":\"tuple[]\"}],\"name\":\"multiAttestByDelegation\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structRevocationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"internalType\":\"structMultiRevocationRequest[]\",\"name\":\"multiRequests\",\"type\":\"tuple[]\"}],\"name\":\"multiRevoke\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structRevocationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structSignature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\"}],\"internalType\":\"structMultiDelegatedRevocationRequest[]\",\"name\":\"multiDelegatedRequests\",\"type\":\"tuple[]\"}],\"name\":\"multiRevokeByDelegation\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"data\",\"type\":\"bytes32[]\"}],\"name\":\"multiRevokeOffchain\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"data\",\"type\":\"bytes32[]\"}],\"name\":\"multiTimestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structRevocationRequestData\",\"name\":\"data\",\"type\":\"tuple\"}],\"internalType\":\"structRevocationRequest\",\"name\":\"request\",\"type\":\"tuple\"}],\"name\":\"revoke\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structRevocationRequestData\",\"name\":\"data\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structSignature\",\"name\":\"signature\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\"}],\"internalType\":\"structDelegatedRevocationRequest\",\"name\":\"delegatedRequest\",\"type\":\"tuple\"}],\"name\":\"revokeByDelegation\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"name\":\"revokeOffchain\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101c06040523480156200001257600080fd5b50604080518082018252600381526245415360e81b602080830191825283518085019094526005845264312e302e3160d81b9084019081526001608081905260a052600060c052825190912083519091206101408290526101608190524661010052919291839183917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ec8184846040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b60e0523061012052610180525050505060208201516101a052506200010e9050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516144d76200018a600039600061054101526000612685015260006126d4015260006126af01526000612608015260006126320152600061265c015260006108730152600061084a0152600061082101526144d76000f3fe6080604052600436106101805760003560e01c8063b469318d116100d6578063e45d03f91161007f578063ed24911d11610059578063ed24911d1461049e578063f10b5cc8146104b3578063f17325e7146104e257600080fd5b8063e45d03f914610458578063e57a6b1b1461046b578063e71ff3651461047e57600080fd5b8063d45c4435116100b0578063d45c4435146103cf578063e13458fc14610406578063e30bb5631461041957600080fd5b8063b469318d14610322578063b83010d31461037c578063cf190f34146103af57600080fd5b8063469262671161013857806354fd4d501161011257806354fd4d50146102cd578063831e05a1146102e2578063a3112a64146102f557600080fd5b806346926267146102855780634cb7e9e51461029a5780634d003070146102ad57600080fd5b806317d7de7c1161016957806317d7de7c146102005780632d0335ab1461022257806344adc90e1461026557600080fd5b806312b11a171461018557806313893f61146101c7575b600080fd5b34801561019157600080fd5b507fdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de615b6040519081526020015b60405180910390f35b3480156101d357600080fd5b506101e76101e23660046133a9565b6104f5565b60405167ffffffffffffffff90911681526020016101be565b34801561020c57600080fd5b5061021561053a565b6040516101be9190613459565b34801561022e57600080fd5b506101b461023d36600461349e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6102786102733660046133a9565b61056a565b6040516101be91906134bb565b6102986102933660046134ff565b6106a1565b005b6102986102a83660046133a9565b610725565b3480156102b957600080fd5b506101e76102c8366004613517565b61080d565b3480156102d957600080fd5b5061021561081a565b6102786102f03660046133a9565b6108bd565b34801561030157600080fd5b50610315610310366004613517565b610b0e565b6040516101be9190613617565b34801561032e57600080fd5b506101e761033d36600461362a565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152603460209081526040808320938352929052205467ffffffffffffffff1690565b34801561038857600080fd5b507fa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a996506101b4565b3480156103bb57600080fd5b506101e76103ca366004613517565b610cd1565b3480156103db57600080fd5b506101e76103ea366004613517565b60009081526033602052604090205467ffffffffffffffff1690565b6101b4610414366004613656565b610cdf565b34801561042557600080fd5b50610448610434366004613517565b600090815260326020526040902054151590565b60405190151581526020016101be565b6102986104663660046133a9565b610de2565b610298610479366004613691565b610f5d565b34801561048a57600080fd5b506101e76104993660046133a9565b611002565b3480156104aa57600080fd5b506101b461103a565b3480156104bf57600080fd5b5060405173420000000000000000000000000000000000002081526020016101be565b6101b46104f03660046136a3565b611044565b60004282825b8181101561052e5761052633878784818110610519576105196136de565b9050602002013585611102565b6001016104fb565b50909150505b92915050565b60606105657f0000000000000000000000000000000000000000000000000000000000000000611201565b905090565b606060008267ffffffffffffffff8111156105875761058761370d565b6040519080825280602002602001820160405280156105ba57816020015b60608152602001906001900390816105a55790505b509050600034815b8581101561068c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8601811436888884818110610602576106026136de565b9050602002810190610614919061373c565b9050600061063b823561062a602085018561377a565b610633916139f3565b33888761138f565b805190915061064a9086613a96565b94508060200151878581518110610663576106636136de565b6020026020010181905250806020015151860195505050506106858160010190565b90506105c2565b506106978383611aa1565b9695505050505050565b604080516001808252818301909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816106b85790505090506106f336839003830160208401613af8565b81600081518110610706576107066136de565b602090810291909101015261072082358233346001611b6e565b505050565b3460005b82811015610807577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8301811436858584818110610769576107696136de565b905060200281019061077b919061373c565b90506107e8813561078f6020840184613b14565b808060200260200160405190810160405280939291908181526020016000905b828210156107db576107cc60408302860136819003810190613af8565b815260200190600101906107af565b5050505050338786611b6e565b6107f29085613a96565b935050506108008160010190565b9050610729565b50505050565b60004261053483826121a8565b60606108457f000000000000000000000000000000000000000000000000000000000000000061226a565b61086e7f000000000000000000000000000000000000000000000000000000000000000061226a565b6108977f000000000000000000000000000000000000000000000000000000000000000061226a565b6040516020016108a993929190613b7c565b604051602081830303815290604052905090565b606060008267ffffffffffffffff8111156108da576108da61370d565b60405190808252806020026020018201604052801561090d57816020015b60608152602001906001900390816108f85790505b509050600034815b8581101561068c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8601811436888884818110610955576109556136de565b90506020028101906109679190613bf2565b9050366000610979602084018461377a565b909250905080158061099957506109936040840184613c26565b82141590505b156109d0576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a9257610a8a604051806080016040528086600001358152602001858585818110610a0557610a056136de565b9050602002810190610a179190613c8d565b610a2090613cc1565b8152602001610a326040880188613c26565b85818110610a4257610a426136de565b905060600201803603810190610a589190613d38565b8152602001610a6d608088016060890161349e565b73ffffffffffffffffffffffffffffffffffffffff1690526123a7565b6001016109d3565b506000610abb8435610aa484866139f3565b610ab4608088016060890161349e565b8a8961138f565b8051909150610aca9088613a96565b96508060200151898781518110610ae357610ae36136de565b6020026020010181905250806020015151880197505050505050610b078160010190565b9050610915565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082019290925261012081019190915260008281526032602090815260409182902082516101408101845281548152600182015492810192909252600281015467ffffffffffffffff808216948401949094526801000000000000000081048416606084015270010000000000000000000000000000000090049092166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff16151561010082015260068201805491929161012084019190610c4890613d54565b80601f0160208091040260200160405190810160405280929190818152602001828054610c7490613d54565b8015610cc15780601f10610c9657610100808354040283529160200191610cc1565b820191906000526020600020905b815481529060010190602001808311610ca457829003601f168201915b5050505050815250509050919050565b600042610534338483611102565b6000610cf2610ced83613da1565b6123a7565b604080516001808252818301909252600091816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610d09579050509050610d776020840184613c8d565b610d8090613cc1565b81600081518110610d9357610d936136de565b6020908102919091010152610dbc833582610db460c0870160a0880161349e565b34600161138f565b60200151600081518110610dd257610dd26136de565b6020026020010151915050919050565b3460005b82811015610807577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830181146000858584818110610e2757610e276136de565b9050602002810190610e399190613bf2565b610e4290613e86565b60208101518051919250901580610e5f5750816040015151815114155b15610e96576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8151811015610f2757610f1f604051806080016040528085600001518152602001848481518110610ecc57610ecc6136de565b6020026020010151815260200185604001518481518110610eef57610eef6136de565b60200260200101518152602001856060015173ffffffffffffffffffffffffffffffffffffffff16815250612560565b600101610e99565b50610f3d82600001518284606001518887611b6e565b610f479086613a96565b9450505050610f568160010190565b9050610de6565b610f74610f6f36839003830183613f65565b612560565b604080516001808252818301909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081610f8b579050509050610fc636839003830160208401613af8565b81600081518110610fd957610fd96136de565b6020908102919091010152610720823582610ffa60e0860160c0870161349e565b346001611b6e565b60004282825b8181101561052e57611032868683818110611025576110256136de565b90506020020135846121a8565b600101611008565b60006105656125ee565b604080516001808252818301909252600091829190816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161105e5790505090506110cc6020840184613c8d565b6110d590613cc1565b816000815181106110e8576110e86136de565b6020908102919091010152610dbc8335823334600161138f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152603460209081526040808320858452918290529091205467ffffffffffffffff1615611176576040517fec9d6eeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526020829052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff861690811790915590519091859173ffffffffffffffffffffffffffffffffffffffff8816917f92a1f7a41a7c585a8b09e25b195e225b1d43248daca46b0faf9e0792777a222991a450505050565b604080516020808252818301909252606091600091906020820181803683370190505090506000805b60208110156112cc576000858260208110611247576112476136de565b1a60f81b90507fff00000000000000000000000000000000000000000000000000000000000000811660000361127d57506112cc565b80848481518110611290576112906136de565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350506001918201910161122a565b5060008167ffffffffffffffff8111156112e8576112e861370d565b6040519080825280601f01601f191660200182016040528015611312576020820181803683370190505b50905060005b8281101561138657838181518110611332576113326136de565b602001015160f81c60f81b82828151811061134f5761134f6136de565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101611318565b50949350505050565b60408051808201909152600081526060602082015284516040805180820190915260008152606060208201528167ffffffffffffffff8111156113d4576113d461370d565b6040519080825280602002602001820160405280156113fd578160200160208202803683370190505b5060208201526040517fa2ea7c6e000000000000000000000000000000000000000000000000000000008152600481018990526000907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa15801561146f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114b59190810190613fc1565b80519091506114f0576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008367ffffffffffffffff81111561150b5761150b61370d565b6040519080825280602002602001820160405280156115aa57816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816115295790505b50905060008467ffffffffffffffff8111156115c8576115c861370d565b6040519080825280602002602001820160405280156115f1578160200160208202803683370190505b50905060005b85811015611a805760008b8281518110611613576116136136de565b60200260200101519050600067ffffffffffffffff16816020015167ffffffffffffffff161415801561165e57504267ffffffffffffffff16816020015167ffffffffffffffff1611155b15611695576040517f08e8b93700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84604001511580156116a8575080604001515b156116df576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052806000801b81526020018f81526020016117034290565b67ffffffffffffffff168152602001836020015167ffffffffffffffff168152602001600067ffffffffffffffff16815260200183606001518152602001836000015173ffffffffffffffffffffffffffffffffffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815260200183604001511515815260200183608001518152509050600080600090505b6117a58382612722565b600081815260326020526040902054909250156117c45760010161179b565b81835260008281526032602090815260409182902085518155908501516001820155908401516002820180546060870151608088015167ffffffffffffffff908116700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff92821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169190951617919091171691909117905560a0840151600382015560c084015160048201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560e0850151600583018054610100880151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff0000000000000000000000000000000000000000009091169290931691909117919091179055610120840151849190600682019061194490826140e7565b50505060608401511561199b57606084015160009081526032602052604090205461199b576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828786815181106119ae576119ae6136de565b60200260200101819052508360a001518686815181106119d0576119d06136de565b60200260200101818152505081896020015186815181106119f3576119f36136de565b6020026020010181815250508f8e73ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff167f8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b3585604051611a6391815260200190565b60405180910390a450505050611a798160010190565b90506115f7565b50611a9083838360008c8c612781565b845250919998505050505050505050565b606060008267ffffffffffffffff811115611abe57611abe61370d565b604051908082528060200260200182016040528015611ae7578160200160208202803683370190505b5090506000805b855181101561052e576000868281518110611b0b57611b0b6136de565b6020026020010151905060005b8151811015611b6457818181518110611b3357611b336136de565b6020026020010151858581518110611b4d57611b4d6136de565b602090810291909101015260019384019301611b18565b5050600101611aee565b6040517fa2ea7c6e0000000000000000000000000000000000000000000000000000000081526004810186905260009081907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa158015611bdc573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611c229190810190613fc1565b8051909150611c5d576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855160008167ffffffffffffffff811115611c7a57611c7a61370d565b604051908082528060200260200182016040528015611d1957816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611c985790505b50905060008267ffffffffffffffff811115611d3757611d3761370d565b604051908082528060200260200182016040528015611d60578160200160208202803683370190505b50905060005b8381101561218a5760008a8281518110611d8257611d826136de565b6020908102919091018101518051600090815260329092526040909120805491925090611ddb576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8c816001015414611e18576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015473ffffffffffffffffffffffffffffffffffffffff8c8116911614611e6e576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015474010000000000000000000000000000000000000000900460ff16611ec4576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002810154700100000000000000000000000000000000900467ffffffffffffffff1615611f1e576040517f905e710700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b426002820180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff811670010000000000000000000000000000000067ffffffffffffffff948516810291821793849055604080516101408101825287548152600188015460208201529386169286169290921791830191909152680100000000000000008304841660608301529091049091166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff161515610100820152600682018054839161012084019161202a90613d54565b80601f016020809104026020016040519081016040528092919081815260200182805461205690613d54565b80156120a35780601f10612078576101008083540402835291602001916120a3565b820191906000526020600020905b81548152906001019060200180831161208657829003601f168201915b5050505050815250508584815181106120be576120be6136de565b602002602001018190525081602001518484815181106120e0576120e06136de565b60200260200101818152505080600101548b73ffffffffffffffffffffffffffffffffffffffff168260040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167ff930a6e2523c9cc298691873087a740550b8fc85a0680830414c148ed927f615856000015160405161217891815260200190565b60405180910390a45050600101611d66565b5061219a84838360018b8b612781565b9a9950505050505050505050565b60008281526033602052604090205467ffffffffffffffff16156121f8576040517f2e26794600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526033602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051909184917f5aafceeb1c7ad58e4a84898bdee37c02c0fc46e7d24e6b60e8209449f183459f9190a35050565b6060816000036122ad57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156122d757806122c181614201565b91506122d09050600a83614268565b91506122b1565b60008167ffffffffffffffff8111156122f2576122f261370d565b6040519080825280601f01601f19166020018201604052801561231c576020820181803683370190505b5090505b841561239f57612331600183613a96565b915061233e600a8661427c565b612349906030614290565b60f81b81838151811061235e5761235e6136de565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612398600a86614268565b9450612320565b949350505050565b60208082015160408084015160608086015173ffffffffffffffffffffffffffffffffffffffff1660009081528086528381208054600181019091558751865187890151878901519589015160808a01518051908c01209851999a9799949895976124ad97612492977fdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de619791939290918c9101978852602088019690965273ffffffffffffffffffffffffffffffffffffffff94909416604087015267ffffffffffffffff9290921660608601521515608085015260a084015260c083015260e08201526101000190565b60405160208183030381529060405280519060200120612b5b565b905061252385606001518285602001518660400151876000015160405160200161250f93929190928352602083019190915260f81b7fff0000000000000000000000000000000000000000000000000000000000000016604082015260410190565b604051602081830303815290604052612b6e565b612559576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b60208181015160408084015160608086015173ffffffffffffffffffffffffffffffffffffffff1660009081528086528381208054600181019091558751865186517fa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a99650998101999099529588015291860193909352608085018190529293909291906124ad9060a001612492565b60003073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561265457507f000000000000000000000000000000000000000000000000000000000000000046145b1561267e57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60208083015160c084015160e0850151604080870151606088015161010089015160a08a01516101208b0151945160009961276399989796918c91016142a3565b60405160208183030381529060405280519060200120905092915050565b845160009060018190036127d9576127d188886000815181106127a6576127a66136de565b6020026020010151886000815181106127c1576127c16136de565b6020026020010151888888612d3d565b915050610697565b602088015173ffffffffffffffffffffffffffffffffffffffff811661286b5760005b8281101561285f57878181518110612816576128166136de565b6020026020010151600014612857576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016127fc565b50600092505050610697565b6000805b8381101561299557600089828151811061288b5761288b6136de565b602002602001015190508060001415801561291257508373ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129109190614381565b155b15612949576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87811115612983576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9687900396919091019060010161286f565b508615612a70576040517f88e5b2d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906388e5b2d99083906129f2908d908d9060040161439e565b60206040518083038185885af1158015612a10573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612a359190614381565b612a6b576040517fbf2f3a8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b3f565b6040517f91db0b7e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906391db0b7e908390612ac6908d908d9060040161439e565b60206040518083038185885af1158015612ae4573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612b099190614381565b612b3f576040517fe8bee83900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415612b4e57612b4e86613053565b9998505050505050505050565b6000610534612b686125ee565b83613066565b6000806000612b7d85856130a8565b90925090506000816004811115612b9657612b96614457565b148015612bce57508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b15612bde57600192505050612d36565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b8888604051602401612c13929190614486565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612c9c919061449f565b600060405180830381855afa9150503d8060008114612cd7576040519150601f19603f3d011682016040523d82523d6000602084013e612cdc565b606091505b5091509150818015612cef575080516020145b8015612d2f575080517f1626ba7e0000000000000000000000000000000000000000000000000000000090612d2d90830160209081019084016144b1565b145b9450505050505b9392505050565b602086015160009073ffffffffffffffffffffffffffffffffffffffff8116612da2578515612d98576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000915050610697565b8515801590612e1d57508073ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e1b9190614381565b155b15612e54576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83861115612e8e576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85840393508415612f6b576040517fe49617e100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e49617e1908890612eed908b90600401613617565b60206040518083038185885af1158015612f0b573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612f309190614381565b612f66576040517fccf3bb2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613038565b6040517fe60c350500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e60c3505908890612fbf908b90600401613617565b60206040518083038185885af1158015612fdd573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906130029190614381565b613038576040517fbd8ba84d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82156130475761304784613053565b50939695505050505050565b80156130635761306333826130ed565b50565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526022810183905260428101829052600090606201612763565b60008082516041036130de5760208301516040840151606085015160001a6130d28782858561324c565b945094505050506130e6565b506000905060025b9250929050565b8047101561315c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064015b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146131b6576040519150601f19603f3d011682016040523d82523d6000602084013e6131bb565b606091505b5050905080610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401613153565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613283575060009050600361335b565b8460ff16601b1415801561329b57508460ff16601c14155b156132ac575060009050600461335b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015613300573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166133545760006001925092505061335b565b9150600090505b94509492505050565b60008083601f84011261337657600080fd5b50813567ffffffffffffffff81111561338e57600080fd5b6020830191508360208260051b85010111156130e657600080fd5b600080602083850312156133bc57600080fd5b823567ffffffffffffffff8111156133d357600080fd5b6133df85828601613364565b90969095509350505050565b60005b838110156134065781810151838201526020016133ee565b50506000910152565b600081518084526134278160208601602086016133eb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d36602083018461340f565b73ffffffffffffffffffffffffffffffffffffffff8116811461306357600080fd5b80356134998161346c565b919050565b6000602082840312156134b057600080fd5b8135612d368161346c565b6020808252825182820181905260009190848201906040850190845b818110156134f3578351835292840192918401916001016134d7565b50909695505050505050565b60006060828403121561351157600080fd5b50919050565b60006020828403121561352957600080fd5b5035919050565b60006101408251845260208301516020850152604083015161355e604086018267ffffffffffffffff169052565b50606083015161357a606086018267ffffffffffffffff169052565b506080830151613596608086018267ffffffffffffffff169052565b5060a083015160a085015260c08301516135c860c086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e08301516135f060e086018273ffffffffffffffffffffffffffffffffffffffff169052565b5061010083810151151590850152610120808401518186018390526106978387018261340f565b602081526000612d366020830184613530565b6000806040838503121561363d57600080fd5b82356136488161346c565b946020939093013593505050565b60006020828403121561366857600080fd5b813567ffffffffffffffff81111561367f57600080fd5b820160c08185031215612d3657600080fd5b600060e0828403121561351157600080fd5b6000602082840312156136b557600080fd5b813567ffffffffffffffff8111156136cc57600080fd5b820160408185031215612d3657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261377057600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126137af57600080fd5b83018035915067ffffffffffffffff8211156137ca57600080fd5b6020019150600581901b36038213156130e657600080fd5b60405160c0810167ffffffffffffffff811182821017156138055761380561370d565b60405290565b6040516080810167ffffffffffffffff811182821017156138055761380561370d565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138755761387561370d565b604052919050565b600067ffffffffffffffff8211156138975761389761370d565b5060051b60200190565b801515811461306357600080fd5b8035613499816138a1565b600067ffffffffffffffff8211156138d4576138d461370d565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261391157600080fd5b813561392461391f826138ba565b61382e565b81815284602083860101111561393957600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561396857600080fd5b6139706137e2565b9050813561397d8161346c565b8152602082013567ffffffffffffffff808216821461399b57600080fd5b8160208401526139ad604085016138af565b60408401526060840135606084015260808401359150808211156139d057600080fd5b506139dd84828501613900565b60808301525060a082013560a082015292915050565b6000613a0161391f8461387d565b80848252602080830192508560051b850136811115613a1f57600080fd5b855b81811015613a5b57803567ffffffffffffffff811115613a415760008081fd5b613a4d36828a01613956565b865250938201938201613a21565b50919695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561053457610534613a67565b600060408284031215613abb57600080fd5b6040516040810181811067ffffffffffffffff82111715613ade57613ade61370d565b604052823581526020928301359281019290925250919050565b600060408284031215613b0a57600080fd5b612d368383613aa9565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613b4957600080fd5b83018035915067ffffffffffffffff821115613b6457600080fd5b6020019150600681901b36038213156130e657600080fd5b60008451613b8e8184602089016133eb565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551613bca816001850160208a016133eb565b60019201918201528351613be58160028401602088016133eb565b0160020195945050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261377057600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613c5b57600080fd5b83018035915067ffffffffffffffff821115613c7657600080fd5b60200191506060810236038213156130e657600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4183360301811261377057600080fd5b60006105343683613956565b600060608284031215613cdf57600080fd5b6040516060810181811067ffffffffffffffff82111715613d0257613d0261370d565b604052905080823560ff81168114613d1957600080fd5b8082525060208301356020820152604083013560408201525092915050565b600060608284031215613d4a57600080fd5b612d368383613ccd565b600181811c90821680613d6857607f821691505b602082108103613511577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060c08236031215613db357600080fd5b613dbb61380b565b82358152602083013567ffffffffffffffff811115613dd957600080fd5b613de536828601613956565b602083015250613df83660408501613ccd565b604082015260a0830135613e0b8161346c565b606082015292915050565b600082601f830112613e2757600080fd5b81356020613e3761391f8361387d565b82815260609283028501820192828201919087851115613e5657600080fd5b8387015b85811015613e7957613e6c8982613ccd565b8452928401928101613e5a565b5090979650505050505050565b600060808236031215613e9857600080fd5b613ea061380b565b8235815260208084013567ffffffffffffffff80821115613ec057600080fd5b9085019036601f830112613ed357600080fd5b8135613ee161391f8261387d565b81815260069190911b83018401908481019036831115613f0057600080fd5b938501935b82851015613f2957613f173686613aa9565b82528582019150604085019450613f05565b80868801525050506040860135925080831115613f4557600080fd5b5050613f5336828601613e16565b604083015250613e0b6060840161348e565b600060e08284031215613f7757600080fd5b613f7f61380b565b82358152613f908460208501613aa9565b6020820152613fa28460608501613ccd565b604082015260c0830135613fb58161346c565b60608201529392505050565b60006020808385031215613fd457600080fd5b825167ffffffffffffffff80821115613fec57600080fd5b908401906080828703121561400057600080fd5b61400861380b565b82518152838301516140198161346c565b81850152604083015161402b816138a1565b604082015260608301518281111561404257600080fd5b80840193505086601f84011261405757600080fd5b8251915061406761391f836138ba565b828152878584860101111561407b57600080fd5b61408a838683018787016133eb565b60608201529695505050505050565b601f82111561072057600081815260208120601f850160051c810160208610156140c05750805b601f850160051c820191505b818110156140df578281556001016140cc565b505050505050565b815167ffffffffffffffff8111156141015761410161370d565b6141158161410f8454613d54565b84614099565b602080601f83116001811461416857600084156141325750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556140df565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156141b557888601518255948401946001909101908401614196565b50858210156141f157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361423257614232613a67565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261427757614277614239565b500490565b60008261428b5761428b614239565b500690565b8082018082111561053457610534613a67565b89815260007fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808b60601b166020840152808a60601b166034840152507fffffffffffffffff000000000000000000000000000000000000000000000000808960c01b166048840152808860c01b1660508401525085151560f81b6058830152846059830152835161433c8160798501602088016133eb565b80830190507fffffffff000000000000000000000000000000000000000000000000000000008460e01b166079820152607d81019150509a9950505050505050505050565b60006020828403121561439357600080fd5b8151612d36816138a1565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b83811015614413577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552614401868351613530565b955093820193908201906001016143c7565b50508584038187015286518085528782019482019350915060005b8281101561444a5784518452938101939281019260010161442e565b5091979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061239f604083018461340f565b600082516137708184602087016133eb565b6000602082840312156144c357600080fd5b505191905056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessDenied\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AlreadyRevoked\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AlreadyRevokedOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AlreadyTimestamped\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeadlineExpired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAttestation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAttestations\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExpirationTime\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNonce\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOffset\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRevocation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRevocations\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSchema\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidVerifier\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Irrevocable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotPayable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongSchema\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"schemaUID\",\"type\":\"bytes32\"}],\"name\":\"Attested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldNonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newNonce\",\"type\":\"uint256\"}],\"name\":\"NonceIncreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"schemaUID\",\"type\":\"bytes32\"}],\"name\":\"Revoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\"}],\"name\":\"RevokedOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\"}],\"name\":\"Timestamped\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structAttestationRequestData\",\"name\":\"data\",\"type\":\"tuple\"}],\"internalType\":\"structAttestationRequest\",\"name\":\"request\",\"type\":\"tuple\"}],\"name\":\"attest\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structAttestationRequestData\",\"name\":\"data\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structSignature\",\"name\":\"signature\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"deadline\",\"type\":\"uint64\"}],\"internalType\":\"structDelegatedAttestationRequest\",\"name\":\"delegatedRequest\",\"type\":\"tuple\"}],\"name\":\"attestByDelegation\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAttestTypeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"name\":\"getAttestation\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"time\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revocationTime\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structAttestation\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDomainSeparator\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"name\":\"getRevokeOffchain\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRevokeTypeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSchemaRegistry\",\"outputs\":[{\"internalType\":\"contractISchemaRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"name\":\"getTimestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newNonce\",\"type\":\"uint256\"}],\"name\":\"increaseNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"name\":\"isAttestationValid\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structAttestationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"internalType\":\"structMultiAttestationRequest[]\",\"name\":\"multiRequests\",\"type\":\"tuple[]\"}],\"name\":\"multiAttest\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structAttestationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structSignature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"deadline\",\"type\":\"uint64\"}],\"internalType\":\"structMultiDelegatedAttestationRequest[]\",\"name\":\"multiDelegatedRequests\",\"type\":\"tuple[]\"}],\"name\":\"multiAttestByDelegation\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structRevocationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\"}],\"internalType\":\"structMultiRevocationRequest[]\",\"name\":\"multiRequests\",\"type\":\"tuple[]\"}],\"name\":\"multiRevoke\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structRevocationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structSignature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"deadline\",\"type\":\"uint64\"}],\"internalType\":\"structMultiDelegatedRevocationRequest[]\",\"name\":\"multiDelegatedRequests\",\"type\":\"tuple[]\"}],\"name\":\"multiRevokeByDelegation\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"data\",\"type\":\"bytes32[]\"}],\"name\":\"multiRevokeOffchain\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"data\",\"type\":\"bytes32[]\"}],\"name\":\"multiTimestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structRevocationRequestData\",\"name\":\"data\",\"type\":\"tuple\"}],\"internalType\":\"structRevocationRequest\",\"name\":\"request\",\"type\":\"tuple\"}],\"name\":\"revoke\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"structRevocationRequestData\",\"name\":\"data\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structSignature\",\"name\":\"signature\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"deadline\",\"type\":\"uint64\"}],\"internalType\":\"structDelegatedRevocationRequest\",\"name\":\"delegatedRequest\",\"type\":\"tuple\"}],\"name\":\"revokeByDelegation\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"name\":\"revokeOffchain\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101c06040523480156200001257600080fd5b50604080518082018252600381526245415360e81b6020808301918252835180850190945260058452640312e322e360dc1b9084019081526001608052600260a052600060c052825190912083519091206101408290526101608190524661010052919291839183917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ec8184846040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b60e0523061012052610180525050505060208201516101a052506200010e9050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516147d16200018a6000396000610703015260006128ff0152600061294e0152600061292901526000612882015260006128ac015260006128d601526000610b7d01526000610b5401526000610b2b01526147d16000f3fe60806040526004361061018b5760003560e01c806395411525116100d6578063d45c44351161007f578063ed24911d11610059578063ed24911d146104c9578063f10b5cc8146104de578063f17325e71461050d57600080fd5b8063d45c443514610433578063e30bb5631461046a578063e71ff365146104a957600080fd5b8063b469318d116100b0578063b469318d14610386578063b83010d3146103e0578063cf190f341461041357600080fd5b80639541152514610333578063a3112a6414610346578063a6d4dbc71461037357600080fd5b806344adc90e116101385780634d003070116101125780634d003070146102de57806354fd4d50146102fe57806379f7573a1461031357600080fd5b806344adc90e1461029857806346926267146102b85780634cb7e9e5146102cb57600080fd5b806317d7de7c1161016957806317d7de7c146102205780632d0335ab146102425780633c0427151461028557600080fd5b80630eabf6601461019057806312b11a17146101a557806313893f61146101e7575b600080fd5b6101a361019e366004613643565b610520565b005b3480156101b157600080fd5b507ff83bb2b0ede93a840239f7e701a54d9bc35f03701f51ae153d601c6947ff3d3f5b6040519081526020015b60405180910390f35b3480156101f357600080fd5b50610207610202366004613643565b6106b7565b60405167ffffffffffffffff90911681526020016101de565b34801561022c57600080fd5b506102356106fc565b6040516101de91906136f3565b34801561024e57600080fd5b506101d461025d366004613738565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101d4610293366004613755565b61072c565b6102ab6102a6366004613643565b61082f565b6040516101de9190613790565b6101a36102c63660046137d4565b6109b0565b6101a36102d9366004613643565b610a34565b3480156102ea57600080fd5b506102076102f93660046137ec565b610b17565b34801561030a57600080fd5b50610235610b24565b34801561031f57600080fd5b506101a361032e3660046137ec565b610bc7565b6102ab610341366004613643565b610c5e565b34801561035257600080fd5b506103666103613660046137ec565b610ed1565b6040516101de91906138ec565b6101a36103813660046138ff565b611094565b34801561039257600080fd5b506102076103a1366004613912565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152603460209081526040808320938352929052205467ffffffffffffffff1690565b3480156103ec57600080fd5b507f2d4116d8c9824e4c316453e5c2843a1885580374159ce8768603c49085ef424c6101d4565b34801561041f57600080fd5b5061020761042e3660046137ec565b611139565b34801561043f57600080fd5b5061020761044e3660046137ec565b60009081526033602052604090205467ffffffffffffffff1690565b34801561047657600080fd5b506104996104853660046137ec565b600090815260326020526040902054151590565b60405190151581526020016101de565b3480156104b557600080fd5b506102076104c4366004613643565b611147565b3480156104d557600080fd5b506101d461117f565b3480156104ea57600080fd5b5060405173420000000000000000000000000000000000002081526020016101de565b6101d461051b36600461393e565b611189565b348160005b818110156106b0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82018114600086868481811061056657610566613979565b905060200281019061057891906139a8565b61058190613c3e565b602081015180519192509080158061059e57508260400151518114155b156105d5576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610679576106716040518060a001604052808660000151815260200185848151811061060a5761060a613979565b602002602001015181526020018660400151848151811061062d5761062d613979565b60200260200101518152602001866060015173ffffffffffffffffffffffffffffffffffffffff168152602001866080015167ffffffffffffffff16815250611247565b6001016105d8565b5061068f83600001518385606001518a88611434565b6106999088613d68565b9650505050506106a98160010190565b9050610525565b5050505050565b60004282825b818110156106f0576106e8338787848181106106db576106db613979565b9050602002013585611a63565b6001016106bd565b50909150505b92915050565b60606107277f0000000000000000000000000000000000000000000000000000000000000000611b62565b905090565b600061073f61073a83613e9d565b611cf0565b604080516001808252818301909252600091816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816107565790505090506107c46020840184613f18565b6107cd90613f4c565b816000815181106107e0576107e0613979565b602090810291909101015261080983358261080160c0870160a08801613738565b346001611e6d565b6020015160008151811061081f5761081f613979565b6020026020010151915050919050565b60608160008167ffffffffffffffff81111561084d5761084d6139e6565b60405190808252806020026020018201604052801561088057816020015b606081526020019060019003908161086b5790505b509050600034815b8481101561099a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85018114368989848181106108c8576108c8613979565b90506020028101906108da9190613f58565b90506108e96020820182613f8c565b9050600003610924576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061094982356109386020850185613f8c565b61094191613ff4565b338887611e6d565b80519091506109589086613d68565b9450806020015187858151811061097157610971613979565b6020026020010181905250806020015151860195505050506109938160010190565b9050610888565b506109a5838361257f565b979650505050505050565b604080516001808252818301909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816109c7579050509050610a0236839003830160208401614068565b81600081518110610a1557610a15613979565b6020908102919091010152610a2f82358233346001611434565b505050565b348160005b818110156106b0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201811436868684818110610a7957610a79613979565b9050602002810190610a8b9190613f58565b9050610af88135610a9f6020840184614084565b808060200260200160405190810160405280939291908181526020016000905b82821015610aeb57610adc60408302860136819003810190614068565b81526020019060010190610abf565b5050505050338886611434565b610b029086613d68565b94505050610b108160010190565b9050610a39565b6000426106f68382612669565b6060610b4f7f000000000000000000000000000000000000000000000000000000000000000061272b565b610b787f000000000000000000000000000000000000000000000000000000000000000061272b565b610ba17f000000000000000000000000000000000000000000000000000000000000000061272b565b604051602001610bb3939291906140ec565b604051602081830303815290604052905090565b33600090815260208190526040902054808211610c10576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152602081815260409182902084905581518381529081018490527f57b09af877df9068fd60a69d7b21f5576b8b38955812d6ae4ac52942f1e38fb7910160405180910390a15050565b60608160008167ffffffffffffffff811115610c7c57610c7c6139e6565b604051908082528060200260200182016040528015610caf57816020015b6060815260200190600190039081610c9a5790505b509050600034815b8481101561099a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8501811436898984818110610cf757610cf7613979565b9050602002810190610d0991906139a8565b9050366000610d1b6020840184613f8c565b909250905080801580610d3c5750610d366040850185614162565b90508114155b15610d73576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610e5457610e4c6040518060a0016040528087600001358152602001868685818110610da857610da8613979565b9050602002810190610dba9190613f18565b610dc390613f4c565b8152602001610dd56040890189614162565b85818110610de557610de5613979565b905060600201803603810190610dfb91906141c9565b8152602001610e106080890160608a01613738565b73ffffffffffffffffffffffffffffffffffffffff168152602001610e3b60a0890160808a016141e5565b67ffffffffffffffff169052611cf0565b600101610d76565b506000610e7d8535610e668587613ff4565b610e766080890160608a01613738565b8b8a611e6d565b8051909150610e8c9089613d68565b975080602001518a8881518110610ea557610ea5613979565b602002602001018190525080602001515189019850505050505050610eca8160010190565b9050610cb7565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082019290925261012081019190915260008281526032602090815260409182902082516101408101845281548152600182015492810192909252600281015467ffffffffffffffff808216948401949094526801000000000000000081048416606084015270010000000000000000000000000000000090049092166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff1615156101008201526006820180549192916101208401919061100b90614200565b80601f016020809104026020016040519081016040528092919081815260200182805461103790614200565b80156110845780601f1061105957610100808354040283529160200191611084565b820191906000526020600020905b81548152906001019060200180831161106757829003601f168201915b5050505050815250509050919050565b6110ab6110a63683900383018361424d565b611247565b604080516001808252818301909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816110c25790505090506110fd36839003830160208401614068565b8160008151811061111057611110613979565b6020908102919091010152610a2f82358261113160e0860160c08701613738565b346001611434565b6000426106f6338483611a63565b60004282825b818110156106f05761117786868381811061116a5761116a613979565b9050602002013584612669565b60010161114d565b6000610727612868565b604080516001808252818301909252600091829190816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816111a35790505090506112116020840184613f18565b61121a90613f4c565b8160008151811061122d5761122d613979565b602090810291909101015261080983358233346001611e6d565b608081015167ffffffffffffffff161580159061127b57504267ffffffffffffffff16816080015167ffffffffffffffff16105b156112b2576040517f1ab7da6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808201516040808401518451835184860151606088015173ffffffffffffffffffffffffffffffffffffffff166000908152968790529386208054959693959394611382947f2d4116d8c9824e4c316453e5c2843a1885580374159ce8768603c49085ef424c94939287611327836142bb565b909155506080808b015160408051602081019890985287019590955260608601939093529184015260a083015267ffffffffffffffff1660c082015260e0015b6040516020818303038152906040528051906020012061299c565b90506113f88460600151828460200151856040015186600001516040516020016113e493929190928352602083019190915260f81b7fff0000000000000000000000000000000000000000000000000000000000000016604082015260410190565b6040516020818303038152906040526129af565b61142e576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b6040517fa2ea7c6e0000000000000000000000000000000000000000000000000000000081526004810186905260009081907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa1580156114a2573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114e891908101906142f3565b8051909150611523576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855160008167ffffffffffffffff811115611540576115406139e6565b6040519080825280602002602001820160405280156115df57816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161155e5790505b50905060008267ffffffffffffffff8111156115fd576115fd6139e6565b604051908082528060200260200182016040528015611626578160200160208202803683370190505b50905060005b83811015611a455760008a828151811061164857611648613979565b60209081029190910181015180516000908152603290925260409091208054919250906116a1576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8c8160010154146116de576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015473ffffffffffffffffffffffffffffffffffffffff8c8116911614611734576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015474010000000000000000000000000000000000000000900460ff1661178a576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002810154700100000000000000000000000000000000900467ffffffffffffffff16156117e4576040517f905e710700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b426002820180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff811670010000000000000000000000000000000067ffffffffffffffff948516810291821793849055604080516101408101825287548152600188015460208201529386169286169290921791830191909152680100000000000000008304841660608301529091049091166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff16151561010082015260068201805483916101208401916118f090614200565b80601f016020809104026020016040519081016040528092919081815260200182805461191c90614200565b80156119695780601f1061193e57610100808354040283529160200191611969565b820191906000526020600020905b81548152906001019060200180831161194c57829003601f168201915b50505050508152505085848151811061198457611984613979565b602002602001018190525081602001518484815181106119a6576119a6613979565b6020026020010181815250508c8b73ffffffffffffffffffffffffffffffffffffffff168685815181106119dc576119dc613979565b602002602001015160c0015173ffffffffffffffffffffffffffffffffffffffff167ff930a6e2523c9cc298691873087a740550b8fc85a0680830414c148ed927f6158560000151604051611a3391815260200190565b60405180910390a4505060010161162c565b50611a5584838360018b8b612b7e565b9a9950505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152603460209081526040808320858452918290529091205467ffffffffffffffff1615611ad7576040517fec9d6eeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526020829052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff861690811790915590519091859173ffffffffffffffffffffffffffffffffffffffff8816917f92a1f7a41a7c585a8b09e25b195e225b1d43248daca46b0faf9e0792777a222991a450505050565b604080516020808252818301909252606091600091906020820181803683370190505090506000805b6020811015611c2d576000858260208110611ba857611ba8613979565b1a60f81b90507fff000000000000000000000000000000000000000000000000000000000000008116600003611bde5750611c2d565b80848481518110611bf157611bf1613979565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053505060019182019101611b8b565b5060008167ffffffffffffffff811115611c4957611c496139e6565b6040519080825280601f01601f191660200182016040528015611c73576020820181803683370190505b50905060005b82811015611ce757838181518110611c9357611c93613979565b602001015160f81c60f81b828281518110611cb057611cb0613979565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101611c79565b50949350505050565b608081015167ffffffffffffffff1615801590611d2457504267ffffffffffffffff16816080015167ffffffffffffffff16105b15611d5b576040517f1ab7da6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208082015160408084015184518351848601518486015160608088015160808901518051908b012060a08a0151928c015173ffffffffffffffffffffffffffffffffffffffff1660009081529a8b9052978a208054999a97999798611382987ff83bb2b0ede93a840239f7e701a54d9bc35f03701f51ae153d601c6947ff3d3f989796959491928b611ded836142bb565b909155506080808f015160408051602081019c909c528b019990995273ffffffffffffffffffffffffffffffffffffffff90971660608a015267ffffffffffffffff9586169689019690965292151560a088015260c087019190915260e08601526101008501526101208401919091521661014082015261016001611367565b60408051808201909152600081526060602082015284516040805180820190915260008152606060208201528167ffffffffffffffff811115611eb257611eb26139e6565b604051908082528060200260200182016040528015611edb578160200160208202803683370190505b5060208201526040517fa2ea7c6e000000000000000000000000000000000000000000000000000000008152600481018990526000907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa158015611f4d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611f9391908101906142f3565b8051909150611fce576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008367ffffffffffffffff811115611fe957611fe96139e6565b60405190808252806020026020018201604052801561208857816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816120075790505b50905060008467ffffffffffffffff8111156120a6576120a66139e6565b6040519080825280602002602001820160405280156120cf578160200160208202803683370190505b50905060005b8581101561255e5760008b82815181106120f1576120f1613979565b60200260200101519050600067ffffffffffffffff16816020015167ffffffffffffffff161415801561213c57504267ffffffffffffffff16816020015167ffffffffffffffff1611155b15612173576040517f08e8b93700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460400151158015612186575080604001515b156121bd576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052806000801b81526020018f81526020016121e14290565b67ffffffffffffffff168152602001836020015167ffffffffffffffff168152602001600067ffffffffffffffff16815260200183606001518152602001836000015173ffffffffffffffffffffffffffffffffffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815260200183604001511515815260200183608001518152509050600080600090505b6122838382612f6f565b600081815260326020526040902054909250156122a257600101612279565b81835260008281526032602090815260409182902085518155908501516001820155908401516002820180546060870151608088015167ffffffffffffffff908116700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff92821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169190951617919091171691909117905560a0840151600382015560c084015160048201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560e0850151600583018054610100880151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff000000000000000000000000000000000000000000909116929093169190911791909117905561012084015184919060068201906124229082614419565b505050606084015115612479576060840151600090815260326020526040902054612479576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8287868151811061248c5761248c613979565b60200260200101819052508360a001518686815181106124ae576124ae613979565b60200260200101818152505081896020015186815181106124d1576124d1613979565b6020026020010181815250508f8e73ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff167f8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b358560405161254191815260200190565b60405180910390a4505050506125578160010190565b90506120d5565b5061256e83838360008c8c612b7e565b845250919998505050505050505050565b606060008267ffffffffffffffff81111561259c5761259c6139e6565b6040519080825280602002602001820160405280156125c5578160200160208202803683370190505b508451909150600090815b8181101561265e5760008782815181106125ec576125ec613979565b6020026020010151905060008151905060005b8181101561264a5782818151811061261957612619613979565b602002602001015187878151811061263357612633613979565b6020908102919091010152600195860195016125ff565b5050506126578160010190565b90506125d0565b509195945050505050565b60008281526033602052604090205467ffffffffffffffff16156126b9576040517f2e26794600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526033602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051909184917f5aafceeb1c7ad58e4a84898bdee37c02c0fc46e7d24e6b60e8209449f183459f9190a35050565b60608160000361276e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156127985780612782816142bb565b91506127919050600a83614562565b9150612772565b60008167ffffffffffffffff8111156127b3576127b36139e6565b6040519080825280601f01601f1916602001820160405280156127dd576020820181803683370190505b5090505b8415612860576127f2600183613d68565b91506127ff600a86614576565b61280a90603061458a565b60f81b81838151811061281f5761281f613979565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612859600a86614562565b94506127e1565b949350505050565b60003073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156128ce57507f000000000000000000000000000000000000000000000000000000000000000046145b156128f857507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60006106f66129a9612868565b83612fce565b60008060006129be8585613010565b909250905060008160048111156129d7576129d761459d565b148015612a0f57508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b15612a1f57600192505050612b77565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b8888604051602401612a549291906145cc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612add91906145e5565b600060405180830381855afa9150503d8060008114612b18576040519150601f19603f3d011682016040523d82523d6000602084013e612b1d565b606091505b5091509150818015612b30575080516020145b8015612b70575080517f1626ba7e0000000000000000000000000000000000000000000000000000000090612b6e90830160209081019084016145f7565b145b9450505050505b9392505050565b84516000906001819003612bd657612bce8888600081518110612ba357612ba3613979565b602002602001015188600081518110612bbe57612bbe613979565b6020026020010151888888613055565b915050612f65565b602088015173ffffffffffffffffffffffffffffffffffffffff8116612c775760005b82811015612c5c57878181518110612c1357612c13613979565b6020026020010151600014612c54576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600101612bf9565b508315612c6c57612c6c85613374565b600092505050612f65565b6000808273ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cc5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce99190614610565b905060005b84811015612da65760008a8281518110612d0a57612d0a613979565b6020026020010151905080600003612d225750612d9e565b82612d59576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b88811115612d93576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b978890039792909201915b600101612cee565b508715612e81576040517f88e5b2d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416906388e5b2d9908490612e03908e908e9060040161462d565b60206040518083038185885af1158015612e21573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612e469190614610565b612e7c576040517fbf2f3a8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612f50565b6040517f91db0b7e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416906391db0b7e908490612ed7908e908e9060040161462d565b60206040518083038185885af1158015612ef5573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612f1a9190614610565b612f50576040517fe8bee83900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8515612f5f57612f5f87613374565b50925050505b9695505050505050565b60208083015160c084015160e0850151604080870151606088015161010089015160a08a01516101208b01519451600099612fb099989796918c91016146e6565b60405160208183030381529060405280519060200120905092915050565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526022810183905260428101829052600090606201612fb0565b60008082516041036130465760208301516040840151606085015160001a61303a87828585613387565b9450945050505061304e565b506000905060025b9250929050565b602086015160009073ffffffffffffffffffffffffffffffffffffffff81166130c95785156130b0576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82156130bf576130bf84613374565b6000915050612f65565b85156131b4578073ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561311a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061313e9190614610565b613174576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838611156131ae576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85840393505b841561328c576040517fe49617e100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e49617e190889061320e908b906004016138ec565b60206040518083038185885af115801561322c573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906132519190614610565b613287576040517fccf3bb2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613359565b6040517fe60c350500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e60c35059088906132e0908b906004016138ec565b60206040518083038185885af11580156132fe573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906133239190614610565b613359576040517fbd8ba84d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82156133685761336884613374565b50939695505050505050565b801561338457613384338261349f565b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156133be5750600090506003613496565b8460ff16601b141580156133d657508460ff16601c14155b156133e75750600090506004613496565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561343b573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661348f57600060019250925050613496565b9150600090505b94509492505050565b8047101561350e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064015b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114613568576040519150601f19603f3d011682016040523d82523d6000602084013e61356d565b606091505b5050905080610a2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401613505565b60008083601f84011261361057600080fd5b50813567ffffffffffffffff81111561362857600080fd5b6020830191508360208260051b850101111561304e57600080fd5b6000806020838503121561365657600080fd5b823567ffffffffffffffff81111561366d57600080fd5b613679858286016135fe565b90969095509350505050565b60005b838110156136a0578181015183820152602001613688565b50506000910152565b600081518084526136c1816020860160208601613685565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612b7760208301846136a9565b73ffffffffffffffffffffffffffffffffffffffff8116811461338457600080fd5b803561373381613706565b919050565b60006020828403121561374a57600080fd5b8135612b7781613706565b60006020828403121561376757600080fd5b813567ffffffffffffffff81111561377e57600080fd5b820160e08185031215612b7757600080fd5b6020808252825182820181905260009190848201906040850190845b818110156137c8578351835292840192918401916001016137ac565b50909695505050505050565b6000606082840312156137e657600080fd5b50919050565b6000602082840312156137fe57600080fd5b5035919050565b600061014082518452602083015160208501526040830151613833604086018267ffffffffffffffff169052565b50606083015161384f606086018267ffffffffffffffff169052565b50608083015161386b608086018267ffffffffffffffff169052565b5060a083015160a085015260c083015161389d60c086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e08301516138c560e086018273ffffffffffffffffffffffffffffffffffffffff169052565b506101008381015115159085015261012080840151818601839052612f65838701826136a9565b602081526000612b776020830184613805565b600061010082840312156137e657600080fd5b6000806040838503121561392557600080fd5b823561393081613706565b946020939093013593505050565b60006020828403121561395057600080fd5b813567ffffffffffffffff81111561396757600080fd5b820160408185031215612b7757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618336030181126139dc57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613a3857613a386139e6565b60405290565b60405160c0810167ffffffffffffffff81118282101715613a3857613a386139e6565b6040516080810167ffffffffffffffff81118282101715613a3857613a386139e6565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613acb57613acb6139e6565b604052919050565b600067ffffffffffffffff821115613aed57613aed6139e6565b5060051b60200190565b600060408284031215613b0957600080fd5b6040516040810181811067ffffffffffffffff82111715613b2c57613b2c6139e6565b604052823581526020928301359281019290925250919050565b600060608284031215613b5857600080fd5b6040516060810181811067ffffffffffffffff82111715613b7b57613b7b6139e6565b604052905080823560ff81168114613b9257600080fd5b8082525060208301356020820152604083013560408201525092915050565b600082601f830112613bc257600080fd5b81356020613bd7613bd283613ad3565b613a84565b82815260609283028501820192828201919087851115613bf657600080fd5b8387015b85811015613c1957613c0c8982613b46565b8452928401928101613bfa565b5090979650505050505050565b803567ffffffffffffffff8116811461373357600080fd5b600060a08236031215613c5057600080fd5b613c58613a15565b8235815260208084013567ffffffffffffffff80821115613c7857600080fd5b9085019036601f830112613c8b57600080fd5b8135613c99613bd282613ad3565b81815260069190911b83018401908481019036831115613cb857600080fd5b938501935b82851015613ce157613ccf3686613af7565b82528582019150604085019450613cbd565b80868801525050506040860135925080831115613cfd57600080fd5b5050613d0b36828601613bb1565b604083015250613d1d60608401613728565b6060820152613d2e60808401613c26565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156106f6576106f6613d39565b801515811461338457600080fd5b600067ffffffffffffffff821115613da357613da36139e6565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600060c08284031215613de157600080fd5b613de9613a3e565b90508135613df681613706565b81526020613e05838201613c26565b818301526040830135613e1781613d7b565b604083015260608381013590830152608083013567ffffffffffffffff811115613e4057600080fd5b8301601f81018513613e5157600080fd5b8035613e5f613bd282613d89565b8181528684838501011115613e7357600080fd5b818484018583013760008483830101528060808601525050505060a082013560a082015292915050565b600060e08236031215613eaf57600080fd5b613eb7613a15565b82358152602083013567ffffffffffffffff811115613ed557600080fd5b613ee136828601613dcf565b602083015250613ef43660408501613b46565b604082015260a0830135613f0781613706565b6060820152613d2e60c08401613c26565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff418336030181126139dc57600080fd5b60006106f63683613dcf565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126139dc57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613fc157600080fd5b83018035915067ffffffffffffffff821115613fdc57600080fd5b6020019150600581901b360382131561304e57600080fd5b6000614002613bd284613ad3565b80848252602080830192508560051b85013681111561402057600080fd5b855b8181101561405c57803567ffffffffffffffff8111156140425760008081fd5b61404e36828a01613dcf565b865250938201938201614022565b50919695505050505050565b60006040828403121561407a57600080fd5b612b778383613af7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126140b957600080fd5b83018035915067ffffffffffffffff8211156140d457600080fd5b6020019150600681901b360382131561304e57600080fd5b600084516140fe818460208901613685565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161413a816001850160208a01613685565b60019201918201528351614155816002840160208801613685565b0160020195945050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261419757600080fd5b83018035915067ffffffffffffffff8211156141b257600080fd5b602001915060608102360382131561304e57600080fd5b6000606082840312156141db57600080fd5b612b778383613b46565b6000602082840312156141f757600080fd5b612b7782613c26565b600181811c9082168061421457607f821691505b6020821081036137e6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000610100828403121561426057600080fd5b614268613a15565b823581526142798460208501613af7565b602082015261428b8460608501613b46565b604082015260c083013561429e81613706565b60608201526142af60e08401613c26565b60808201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036142ec576142ec613d39565b5060010190565b6000602080838503121561430657600080fd5b825167ffffffffffffffff8082111561431e57600080fd5b908401906080828703121561433257600080fd5b61433a613a61565b825181528383015161434b81613706565b81850152604083015161435d81613d7b565b604082015260608301518281111561437457600080fd5b80840193505086601f84011261438957600080fd5b82519150614399613bd283613d89565b82815287858486010111156143ad57600080fd5b6143bc83868301878701613685565b60608201529695505050505050565b601f821115610a2f57600081815260208120601f850160051c810160208610156143f25750805b601f850160051c820191505b81811015614411578281556001016143fe565b505050505050565b815167ffffffffffffffff811115614433576144336139e6565b614447816144418454614200565b846143cb565b602080601f83116001811461449a57600084156144645750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555614411565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156144e7578886015182559484019460019091019084016144c8565b508582101561452357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261457157614571614533565b500490565b60008261458557614585614533565b500690565b808201808211156106f6576106f6613d39565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061286060408301846136a9565b600082516139dc818460208701613685565b60006020828403121561460957600080fd5b5051919050565b60006020828403121561462257600080fd5b8151612b7781613d7b565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b838110156146a2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552614690868351613805565b95509382019390820190600101614656565b50508584038187015286518085528782019482019350915060005b828110156146d9578451845293810193928101926001016146bd565b5091979650505050505050565b89815260007fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808b60601b166020840152808a60601b166034840152507fffffffffffffffff000000000000000000000000000000000000000000000000808960c01b166048840152808860c01b1660508401525085151560f81b6058830152846059830152835161477f816079850160208801613685565b80830190507fffffffff000000000000000000000000000000000000000000000000000000008460e01b166079820152607d81019150509a995050505050505050505056fea164736f6c6343000813000a", } // EASABI is the input ABI used to generate the binding from. @@ -656,27 +660,48 @@ func (_EAS *EASTransactorSession) Attest(request AttestationRequest) (*types.Tra return _EAS.Contract.Attest(&_EAS.TransactOpts, request) } -// AttestByDelegation is a paid mutator transaction binding the contract method 0xe13458fc. +// AttestByDelegation is a paid mutator transaction binding the contract method 0x3c042715. // -// Solidity: function attestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256),(uint8,bytes32,bytes32),address) delegatedRequest) payable returns(bytes32) +// Solidity: function attestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256),(uint8,bytes32,bytes32),address,uint64) delegatedRequest) payable returns(bytes32) func (_EAS *EASTransactor) AttestByDelegation(opts *bind.TransactOpts, delegatedRequest DelegatedAttestationRequest) (*types.Transaction, error) { return _EAS.contract.Transact(opts, "attestByDelegation", delegatedRequest) } -// AttestByDelegation is a paid mutator transaction binding the contract method 0xe13458fc. +// AttestByDelegation is a paid mutator transaction binding the contract method 0x3c042715. // -// Solidity: function attestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256),(uint8,bytes32,bytes32),address) delegatedRequest) payable returns(bytes32) +// Solidity: function attestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256),(uint8,bytes32,bytes32),address,uint64) delegatedRequest) payable returns(bytes32) func (_EAS *EASSession) AttestByDelegation(delegatedRequest DelegatedAttestationRequest) (*types.Transaction, error) { return _EAS.Contract.AttestByDelegation(&_EAS.TransactOpts, delegatedRequest) } -// AttestByDelegation is a paid mutator transaction binding the contract method 0xe13458fc. +// AttestByDelegation is a paid mutator transaction binding the contract method 0x3c042715. // -// Solidity: function attestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256),(uint8,bytes32,bytes32),address) delegatedRequest) payable returns(bytes32) +// Solidity: function attestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256),(uint8,bytes32,bytes32),address,uint64) delegatedRequest) payable returns(bytes32) func (_EAS *EASTransactorSession) AttestByDelegation(delegatedRequest DelegatedAttestationRequest) (*types.Transaction, error) { return _EAS.Contract.AttestByDelegation(&_EAS.TransactOpts, delegatedRequest) } +// IncreaseNonce is a paid mutator transaction binding the contract method 0x79f7573a. +// +// Solidity: function increaseNonce(uint256 newNonce) returns() +func (_EAS *EASTransactor) IncreaseNonce(opts *bind.TransactOpts, newNonce *big.Int) (*types.Transaction, error) { + return _EAS.contract.Transact(opts, "increaseNonce", newNonce) +} + +// IncreaseNonce is a paid mutator transaction binding the contract method 0x79f7573a. +// +// Solidity: function increaseNonce(uint256 newNonce) returns() +func (_EAS *EASSession) IncreaseNonce(newNonce *big.Int) (*types.Transaction, error) { + return _EAS.Contract.IncreaseNonce(&_EAS.TransactOpts, newNonce) +} + +// IncreaseNonce is a paid mutator transaction binding the contract method 0x79f7573a. +// +// Solidity: function increaseNonce(uint256 newNonce) returns() +func (_EAS *EASTransactorSession) IncreaseNonce(newNonce *big.Int) (*types.Transaction, error) { + return _EAS.Contract.IncreaseNonce(&_EAS.TransactOpts, newNonce) +} + // MultiAttest is a paid mutator transaction binding the contract method 0x44adc90e. // // Solidity: function multiAttest((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[])[] multiRequests) payable returns(bytes32[]) @@ -698,23 +723,23 @@ func (_EAS *EASTransactorSession) MultiAttest(multiRequests []MultiAttestationRe return _EAS.Contract.MultiAttest(&_EAS.TransactOpts, multiRequests) } -// MultiAttestByDelegation is a paid mutator transaction binding the contract method 0x831e05a1. +// MultiAttestByDelegation is a paid mutator transaction binding the contract method 0x95411525. // -// Solidity: function multiAttestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[],(uint8,bytes32,bytes32)[],address)[] multiDelegatedRequests) payable returns(bytes32[]) +// Solidity: function multiAttestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[],(uint8,bytes32,bytes32)[],address,uint64)[] multiDelegatedRequests) payable returns(bytes32[]) func (_EAS *EASTransactor) MultiAttestByDelegation(opts *bind.TransactOpts, multiDelegatedRequests []MultiDelegatedAttestationRequest) (*types.Transaction, error) { return _EAS.contract.Transact(opts, "multiAttestByDelegation", multiDelegatedRequests) } -// MultiAttestByDelegation is a paid mutator transaction binding the contract method 0x831e05a1. +// MultiAttestByDelegation is a paid mutator transaction binding the contract method 0x95411525. // -// Solidity: function multiAttestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[],(uint8,bytes32,bytes32)[],address)[] multiDelegatedRequests) payable returns(bytes32[]) +// Solidity: function multiAttestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[],(uint8,bytes32,bytes32)[],address,uint64)[] multiDelegatedRequests) payable returns(bytes32[]) func (_EAS *EASSession) MultiAttestByDelegation(multiDelegatedRequests []MultiDelegatedAttestationRequest) (*types.Transaction, error) { return _EAS.Contract.MultiAttestByDelegation(&_EAS.TransactOpts, multiDelegatedRequests) } -// MultiAttestByDelegation is a paid mutator transaction binding the contract method 0x831e05a1. +// MultiAttestByDelegation is a paid mutator transaction binding the contract method 0x95411525. // -// Solidity: function multiAttestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[],(uint8,bytes32,bytes32)[],address)[] multiDelegatedRequests) payable returns(bytes32[]) +// Solidity: function multiAttestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[],(uint8,bytes32,bytes32)[],address,uint64)[] multiDelegatedRequests) payable returns(bytes32[]) func (_EAS *EASTransactorSession) MultiAttestByDelegation(multiDelegatedRequests []MultiDelegatedAttestationRequest) (*types.Transaction, error) { return _EAS.Contract.MultiAttestByDelegation(&_EAS.TransactOpts, multiDelegatedRequests) } @@ -740,23 +765,23 @@ func (_EAS *EASTransactorSession) MultiRevoke(multiRequests []MultiRevocationReq return _EAS.Contract.MultiRevoke(&_EAS.TransactOpts, multiRequests) } -// MultiRevokeByDelegation is a paid mutator transaction binding the contract method 0xe45d03f9. +// MultiRevokeByDelegation is a paid mutator transaction binding the contract method 0x0eabf660. // -// Solidity: function multiRevokeByDelegation((bytes32,(bytes32,uint256)[],(uint8,bytes32,bytes32)[],address)[] multiDelegatedRequests) payable returns() +// Solidity: function multiRevokeByDelegation((bytes32,(bytes32,uint256)[],(uint8,bytes32,bytes32)[],address,uint64)[] multiDelegatedRequests) payable returns() func (_EAS *EASTransactor) MultiRevokeByDelegation(opts *bind.TransactOpts, multiDelegatedRequests []MultiDelegatedRevocationRequest) (*types.Transaction, error) { return _EAS.contract.Transact(opts, "multiRevokeByDelegation", multiDelegatedRequests) } -// MultiRevokeByDelegation is a paid mutator transaction binding the contract method 0xe45d03f9. +// MultiRevokeByDelegation is a paid mutator transaction binding the contract method 0x0eabf660. // -// Solidity: function multiRevokeByDelegation((bytes32,(bytes32,uint256)[],(uint8,bytes32,bytes32)[],address)[] multiDelegatedRequests) payable returns() +// Solidity: function multiRevokeByDelegation((bytes32,(bytes32,uint256)[],(uint8,bytes32,bytes32)[],address,uint64)[] multiDelegatedRequests) payable returns() func (_EAS *EASSession) MultiRevokeByDelegation(multiDelegatedRequests []MultiDelegatedRevocationRequest) (*types.Transaction, error) { return _EAS.Contract.MultiRevokeByDelegation(&_EAS.TransactOpts, multiDelegatedRequests) } -// MultiRevokeByDelegation is a paid mutator transaction binding the contract method 0xe45d03f9. +// MultiRevokeByDelegation is a paid mutator transaction binding the contract method 0x0eabf660. // -// Solidity: function multiRevokeByDelegation((bytes32,(bytes32,uint256)[],(uint8,bytes32,bytes32)[],address)[] multiDelegatedRequests) payable returns() +// Solidity: function multiRevokeByDelegation((bytes32,(bytes32,uint256)[],(uint8,bytes32,bytes32)[],address,uint64)[] multiDelegatedRequests) payable returns() func (_EAS *EASTransactorSession) MultiRevokeByDelegation(multiDelegatedRequests []MultiDelegatedRevocationRequest) (*types.Transaction, error) { return _EAS.Contract.MultiRevokeByDelegation(&_EAS.TransactOpts, multiDelegatedRequests) } @@ -824,23 +849,23 @@ func (_EAS *EASTransactorSession) Revoke(request RevocationRequest) (*types.Tran return _EAS.Contract.Revoke(&_EAS.TransactOpts, request) } -// RevokeByDelegation is a paid mutator transaction binding the contract method 0xe57a6b1b. +// RevokeByDelegation is a paid mutator transaction binding the contract method 0xa6d4dbc7. // -// Solidity: function revokeByDelegation((bytes32,(bytes32,uint256),(uint8,bytes32,bytes32),address) delegatedRequest) payable returns() +// Solidity: function revokeByDelegation((bytes32,(bytes32,uint256),(uint8,bytes32,bytes32),address,uint64) delegatedRequest) payable returns() func (_EAS *EASTransactor) RevokeByDelegation(opts *bind.TransactOpts, delegatedRequest DelegatedRevocationRequest) (*types.Transaction, error) { return _EAS.contract.Transact(opts, "revokeByDelegation", delegatedRequest) } -// RevokeByDelegation is a paid mutator transaction binding the contract method 0xe57a6b1b. +// RevokeByDelegation is a paid mutator transaction binding the contract method 0xa6d4dbc7. // -// Solidity: function revokeByDelegation((bytes32,(bytes32,uint256),(uint8,bytes32,bytes32),address) delegatedRequest) payable returns() +// Solidity: function revokeByDelegation((bytes32,(bytes32,uint256),(uint8,bytes32,bytes32),address,uint64) delegatedRequest) payable returns() func (_EAS *EASSession) RevokeByDelegation(delegatedRequest DelegatedRevocationRequest) (*types.Transaction, error) { return _EAS.Contract.RevokeByDelegation(&_EAS.TransactOpts, delegatedRequest) } -// RevokeByDelegation is a paid mutator transaction binding the contract method 0xe57a6b1b. +// RevokeByDelegation is a paid mutator transaction binding the contract method 0xa6d4dbc7. // -// Solidity: function revokeByDelegation((bytes32,(bytes32,uint256),(uint8,bytes32,bytes32),address) delegatedRequest) payable returns() +// Solidity: function revokeByDelegation((bytes32,(bytes32,uint256),(uint8,bytes32,bytes32),address,uint64) delegatedRequest) payable returns() func (_EAS *EASTransactorSession) RevokeByDelegation(delegatedRequest DelegatedRevocationRequest) (*types.Transaction, error) { return _EAS.Contract.RevokeByDelegation(&_EAS.TransactOpts, delegatedRequest) } @@ -959,14 +984,14 @@ type EASAttested struct { Recipient common.Address Attester common.Address Uid [32]byte - Schema [32]byte + SchemaUID [32]byte Raw types.Log // Blockchain specific contextual infos } // FilterAttested is a free log retrieval operation binding the contract event 0x8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b35. // -// Solidity: event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schema) -func (_EAS *EASFilterer) FilterAttested(opts *bind.FilterOpts, recipient []common.Address, attester []common.Address, schema [][32]byte) (*EASAttestedIterator, error) { +// Solidity: event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID) +func (_EAS *EASFilterer) FilterAttested(opts *bind.FilterOpts, recipient []common.Address, attester []common.Address, schemaUID [][32]byte) (*EASAttestedIterator, error) { var recipientRule []interface{} for _, recipientItem := range recipient { @@ -977,12 +1002,12 @@ func (_EAS *EASFilterer) FilterAttested(opts *bind.FilterOpts, recipient []commo attesterRule = append(attesterRule, attesterItem) } - var schemaRule []interface{} - for _, schemaItem := range schema { - schemaRule = append(schemaRule, schemaItem) + var schemaUIDRule []interface{} + for _, schemaUIDItem := range schemaUID { + schemaUIDRule = append(schemaUIDRule, schemaUIDItem) } - logs, sub, err := _EAS.contract.FilterLogs(opts, "Attested", recipientRule, attesterRule, schemaRule) + logs, sub, err := _EAS.contract.FilterLogs(opts, "Attested", recipientRule, attesterRule, schemaUIDRule) if err != nil { return nil, err } @@ -991,8 +1016,8 @@ func (_EAS *EASFilterer) FilterAttested(opts *bind.FilterOpts, recipient []commo // WatchAttested is a free log subscription operation binding the contract event 0x8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b35. // -// Solidity: event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schema) -func (_EAS *EASFilterer) WatchAttested(opts *bind.WatchOpts, sink chan<- *EASAttested, recipient []common.Address, attester []common.Address, schema [][32]byte) (event.Subscription, error) { +// Solidity: event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID) +func (_EAS *EASFilterer) WatchAttested(opts *bind.WatchOpts, sink chan<- *EASAttested, recipient []common.Address, attester []common.Address, schemaUID [][32]byte) (event.Subscription, error) { var recipientRule []interface{} for _, recipientItem := range recipient { @@ -1003,12 +1028,12 @@ func (_EAS *EASFilterer) WatchAttested(opts *bind.WatchOpts, sink chan<- *EASAtt attesterRule = append(attesterRule, attesterItem) } - var schemaRule []interface{} - for _, schemaItem := range schema { - schemaRule = append(schemaRule, schemaItem) + var schemaUIDRule []interface{} + for _, schemaUIDItem := range schemaUID { + schemaUIDRule = append(schemaUIDRule, schemaUIDItem) } - logs, sub, err := _EAS.contract.WatchLogs(opts, "Attested", recipientRule, attesterRule, schemaRule) + logs, sub, err := _EAS.contract.WatchLogs(opts, "Attested", recipientRule, attesterRule, schemaUIDRule) if err != nil { return nil, err } @@ -1042,7 +1067,7 @@ func (_EAS *EASFilterer) WatchAttested(opts *bind.WatchOpts, sink chan<- *EASAtt // ParseAttested is a log parse operation binding the contract event 0x8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b35. // -// Solidity: event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schema) +// Solidity: event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID) func (_EAS *EASFilterer) ParseAttested(log types.Log) (*EASAttested, error) { event := new(EASAttested) if err := _EAS.contract.UnpackLog(event, "Attested", log); err != nil { @@ -1052,6 +1077,141 @@ func (_EAS *EASFilterer) ParseAttested(log types.Log) (*EASAttested, error) { return event, nil } +// EASNonceIncreasedIterator is returned from FilterNonceIncreased and is used to iterate over the raw logs and unpacked data for NonceIncreased events raised by the EAS contract. +type EASNonceIncreasedIterator struct { + Event *EASNonceIncreased // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *EASNonceIncreasedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(EASNonceIncreased) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(EASNonceIncreased) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *EASNonceIncreasedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *EASNonceIncreasedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// EASNonceIncreased represents a NonceIncreased event raised by the EAS contract. +type EASNonceIncreased struct { + OldNonce *big.Int + NewNonce *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterNonceIncreased is a free log retrieval operation binding the contract event 0x57b09af877df9068fd60a69d7b21f5576b8b38955812d6ae4ac52942f1e38fb7. +// +// Solidity: event NonceIncreased(uint256 oldNonce, uint256 newNonce) +func (_EAS *EASFilterer) FilterNonceIncreased(opts *bind.FilterOpts) (*EASNonceIncreasedIterator, error) { + + logs, sub, err := _EAS.contract.FilterLogs(opts, "NonceIncreased") + if err != nil { + return nil, err + } + return &EASNonceIncreasedIterator{contract: _EAS.contract, event: "NonceIncreased", logs: logs, sub: sub}, nil +} + +// WatchNonceIncreased is a free log subscription operation binding the contract event 0x57b09af877df9068fd60a69d7b21f5576b8b38955812d6ae4ac52942f1e38fb7. +// +// Solidity: event NonceIncreased(uint256 oldNonce, uint256 newNonce) +func (_EAS *EASFilterer) WatchNonceIncreased(opts *bind.WatchOpts, sink chan<- *EASNonceIncreased) (event.Subscription, error) { + + logs, sub, err := _EAS.contract.WatchLogs(opts, "NonceIncreased") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(EASNonceIncreased) + if err := _EAS.contract.UnpackLog(event, "NonceIncreased", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseNonceIncreased is a log parse operation binding the contract event 0x57b09af877df9068fd60a69d7b21f5576b8b38955812d6ae4ac52942f1e38fb7. +// +// Solidity: event NonceIncreased(uint256 oldNonce, uint256 newNonce) +func (_EAS *EASFilterer) ParseNonceIncreased(log types.Log) (*EASNonceIncreased, error) { + event := new(EASNonceIncreased) + if err := _EAS.contract.UnpackLog(event, "NonceIncreased", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + // EASRevokedIterator is returned from FilterRevoked and is used to iterate over the raw logs and unpacked data for Revoked events raised by the EAS contract. type EASRevokedIterator struct { Event *EASRevoked // Event containing the contract specifics and raw log @@ -1124,14 +1284,14 @@ type EASRevoked struct { Recipient common.Address Attester common.Address Uid [32]byte - Schema [32]byte + SchemaUID [32]byte Raw types.Log // Blockchain specific contextual infos } // FilterRevoked is a free log retrieval operation binding the contract event 0xf930a6e2523c9cc298691873087a740550b8fc85a0680830414c148ed927f615. // -// Solidity: event Revoked(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schema) -func (_EAS *EASFilterer) FilterRevoked(opts *bind.FilterOpts, recipient []common.Address, attester []common.Address, schema [][32]byte) (*EASRevokedIterator, error) { +// Solidity: event Revoked(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID) +func (_EAS *EASFilterer) FilterRevoked(opts *bind.FilterOpts, recipient []common.Address, attester []common.Address, schemaUID [][32]byte) (*EASRevokedIterator, error) { var recipientRule []interface{} for _, recipientItem := range recipient { @@ -1142,12 +1302,12 @@ func (_EAS *EASFilterer) FilterRevoked(opts *bind.FilterOpts, recipient []common attesterRule = append(attesterRule, attesterItem) } - var schemaRule []interface{} - for _, schemaItem := range schema { - schemaRule = append(schemaRule, schemaItem) + var schemaUIDRule []interface{} + for _, schemaUIDItem := range schemaUID { + schemaUIDRule = append(schemaUIDRule, schemaUIDItem) } - logs, sub, err := _EAS.contract.FilterLogs(opts, "Revoked", recipientRule, attesterRule, schemaRule) + logs, sub, err := _EAS.contract.FilterLogs(opts, "Revoked", recipientRule, attesterRule, schemaUIDRule) if err != nil { return nil, err } @@ -1156,8 +1316,8 @@ func (_EAS *EASFilterer) FilterRevoked(opts *bind.FilterOpts, recipient []common // WatchRevoked is a free log subscription operation binding the contract event 0xf930a6e2523c9cc298691873087a740550b8fc85a0680830414c148ed927f615. // -// Solidity: event Revoked(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schema) -func (_EAS *EASFilterer) WatchRevoked(opts *bind.WatchOpts, sink chan<- *EASRevoked, recipient []common.Address, attester []common.Address, schema [][32]byte) (event.Subscription, error) { +// Solidity: event Revoked(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID) +func (_EAS *EASFilterer) WatchRevoked(opts *bind.WatchOpts, sink chan<- *EASRevoked, recipient []common.Address, attester []common.Address, schemaUID [][32]byte) (event.Subscription, error) { var recipientRule []interface{} for _, recipientItem := range recipient { @@ -1168,12 +1328,12 @@ func (_EAS *EASFilterer) WatchRevoked(opts *bind.WatchOpts, sink chan<- *EASRevo attesterRule = append(attesterRule, attesterItem) } - var schemaRule []interface{} - for _, schemaItem := range schema { - schemaRule = append(schemaRule, schemaItem) + var schemaUIDRule []interface{} + for _, schemaUIDItem := range schemaUID { + schemaUIDRule = append(schemaUIDRule, schemaUIDItem) } - logs, sub, err := _EAS.contract.WatchLogs(opts, "Revoked", recipientRule, attesterRule, schemaRule) + logs, sub, err := _EAS.contract.WatchLogs(opts, "Revoked", recipientRule, attesterRule, schemaUIDRule) if err != nil { return nil, err } @@ -1207,7 +1367,7 @@ func (_EAS *EASFilterer) WatchRevoked(opts *bind.WatchOpts, sink chan<- *EASRevo // ParseRevoked is a log parse operation binding the contract event 0xf930a6e2523c9cc298691873087a740550b8fc85a0680830414c148ed927f615. // -// Solidity: event Revoked(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schema) +// Solidity: event Revoked(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID) func (_EAS *EASFilterer) ParseRevoked(log types.Log) (*EASRevoked, error) { event := new(EASRevoked) if err := _EAS.contract.UnpackLog(event, "Revoked", log); err != nil { diff --git a/op-bindings/bindings/eas_more.go b/op-bindings/bindings/eas_more.go index 0747fbf58..af65a10bd 100644 --- a/op-bindings/bindings/eas_more.go +++ b/op-bindings/bindings/eas_more.go @@ -13,7 +13,7 @@ const EASStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/E var EASStorageLayout = new(solc.StorageLayout) -var EASDeployedBin = "0x6080604052600436106101805760003560e01c8063b469318d116100d6578063e45d03f91161007f578063ed24911d11610059578063ed24911d1461049e578063f10b5cc8146104b3578063f17325e7146104e257600080fd5b8063e45d03f914610458578063e57a6b1b1461046b578063e71ff3651461047e57600080fd5b8063d45c4435116100b0578063d45c4435146103cf578063e13458fc14610406578063e30bb5631461041957600080fd5b8063b469318d14610322578063b83010d31461037c578063cf190f34146103af57600080fd5b8063469262671161013857806354fd4d501161011257806354fd4d50146102cd578063831e05a1146102e2578063a3112a64146102f557600080fd5b806346926267146102855780634cb7e9e51461029a5780634d003070146102ad57600080fd5b806317d7de7c1161016957806317d7de7c146102005780632d0335ab1461022257806344adc90e1461026557600080fd5b806312b11a171461018557806313893f61146101c7575b600080fd5b34801561019157600080fd5b507fdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de615b6040519081526020015b60405180910390f35b3480156101d357600080fd5b506101e76101e23660046133a9565b6104f5565b60405167ffffffffffffffff90911681526020016101be565b34801561020c57600080fd5b5061021561053a565b6040516101be9190613459565b34801561022e57600080fd5b506101b461023d36600461349e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6102786102733660046133a9565b61056a565b6040516101be91906134bb565b6102986102933660046134ff565b6106a1565b005b6102986102a83660046133a9565b610725565b3480156102b957600080fd5b506101e76102c8366004613517565b61080d565b3480156102d957600080fd5b5061021561081a565b6102786102f03660046133a9565b6108bd565b34801561030157600080fd5b50610315610310366004613517565b610b0e565b6040516101be9190613617565b34801561032e57600080fd5b506101e761033d36600461362a565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152603460209081526040808320938352929052205467ffffffffffffffff1690565b34801561038857600080fd5b507fa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a996506101b4565b3480156103bb57600080fd5b506101e76103ca366004613517565b610cd1565b3480156103db57600080fd5b506101e76103ea366004613517565b60009081526033602052604090205467ffffffffffffffff1690565b6101b4610414366004613656565b610cdf565b34801561042557600080fd5b50610448610434366004613517565b600090815260326020526040902054151590565b60405190151581526020016101be565b6102986104663660046133a9565b610de2565b610298610479366004613691565b610f5d565b34801561048a57600080fd5b506101e76104993660046133a9565b611002565b3480156104aa57600080fd5b506101b461103a565b3480156104bf57600080fd5b5060405173420000000000000000000000000000000000002081526020016101be565b6101b46104f03660046136a3565b611044565b60004282825b8181101561052e5761052633878784818110610519576105196136de565b9050602002013585611102565b6001016104fb565b50909150505b92915050565b60606105657f0000000000000000000000000000000000000000000000000000000000000000611201565b905090565b606060008267ffffffffffffffff8111156105875761058761370d565b6040519080825280602002602001820160405280156105ba57816020015b60608152602001906001900390816105a55790505b509050600034815b8581101561068c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8601811436888884818110610602576106026136de565b9050602002810190610614919061373c565b9050600061063b823561062a602085018561377a565b610633916139f3565b33888761138f565b805190915061064a9086613a96565b94508060200151878581518110610663576106636136de565b6020026020010181905250806020015151860195505050506106858160010190565b90506105c2565b506106978383611aa1565b9695505050505050565b604080516001808252818301909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816106b85790505090506106f336839003830160208401613af8565b81600081518110610706576107066136de565b602090810291909101015261072082358233346001611b6e565b505050565b3460005b82811015610807577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8301811436858584818110610769576107696136de565b905060200281019061077b919061373c565b90506107e8813561078f6020840184613b14565b808060200260200160405190810160405280939291908181526020016000905b828210156107db576107cc60408302860136819003810190613af8565b815260200190600101906107af565b5050505050338786611b6e565b6107f29085613a96565b935050506108008160010190565b9050610729565b50505050565b60004261053483826121a8565b60606108457f000000000000000000000000000000000000000000000000000000000000000061226a565b61086e7f000000000000000000000000000000000000000000000000000000000000000061226a565b6108977f000000000000000000000000000000000000000000000000000000000000000061226a565b6040516020016108a993929190613b7c565b604051602081830303815290604052905090565b606060008267ffffffffffffffff8111156108da576108da61370d565b60405190808252806020026020018201604052801561090d57816020015b60608152602001906001900390816108f85790505b509050600034815b8581101561068c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8601811436888884818110610955576109556136de565b90506020028101906109679190613bf2565b9050366000610979602084018461377a565b909250905080158061099957506109936040840184613c26565b82141590505b156109d0576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a9257610a8a604051806080016040528086600001358152602001858585818110610a0557610a056136de565b9050602002810190610a179190613c8d565b610a2090613cc1565b8152602001610a326040880188613c26565b85818110610a4257610a426136de565b905060600201803603810190610a589190613d38565b8152602001610a6d608088016060890161349e565b73ffffffffffffffffffffffffffffffffffffffff1690526123a7565b6001016109d3565b506000610abb8435610aa484866139f3565b610ab4608088016060890161349e565b8a8961138f565b8051909150610aca9088613a96565b96508060200151898781518110610ae357610ae36136de565b6020026020010181905250806020015151880197505050505050610b078160010190565b9050610915565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082019290925261012081019190915260008281526032602090815260409182902082516101408101845281548152600182015492810192909252600281015467ffffffffffffffff808216948401949094526801000000000000000081048416606084015270010000000000000000000000000000000090049092166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff16151561010082015260068201805491929161012084019190610c4890613d54565b80601f0160208091040260200160405190810160405280929190818152602001828054610c7490613d54565b8015610cc15780601f10610c9657610100808354040283529160200191610cc1565b820191906000526020600020905b815481529060010190602001808311610ca457829003601f168201915b5050505050815250509050919050565b600042610534338483611102565b6000610cf2610ced83613da1565b6123a7565b604080516001808252818301909252600091816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610d09579050509050610d776020840184613c8d565b610d8090613cc1565b81600081518110610d9357610d936136de565b6020908102919091010152610dbc833582610db460c0870160a0880161349e565b34600161138f565b60200151600081518110610dd257610dd26136de565b6020026020010151915050919050565b3460005b82811015610807577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830181146000858584818110610e2757610e276136de565b9050602002810190610e399190613bf2565b610e4290613e86565b60208101518051919250901580610e5f5750816040015151815114155b15610e96576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8151811015610f2757610f1f604051806080016040528085600001518152602001848481518110610ecc57610ecc6136de565b6020026020010151815260200185604001518481518110610eef57610eef6136de565b60200260200101518152602001856060015173ffffffffffffffffffffffffffffffffffffffff16815250612560565b600101610e99565b50610f3d82600001518284606001518887611b6e565b610f479086613a96565b9450505050610f568160010190565b9050610de6565b610f74610f6f36839003830183613f65565b612560565b604080516001808252818301909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081610f8b579050509050610fc636839003830160208401613af8565b81600081518110610fd957610fd96136de565b6020908102919091010152610720823582610ffa60e0860160c0870161349e565b346001611b6e565b60004282825b8181101561052e57611032868683818110611025576110256136de565b90506020020135846121a8565b600101611008565b60006105656125ee565b604080516001808252818301909252600091829190816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161105e5790505090506110cc6020840184613c8d565b6110d590613cc1565b816000815181106110e8576110e86136de565b6020908102919091010152610dbc8335823334600161138f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152603460209081526040808320858452918290529091205467ffffffffffffffff1615611176576040517fec9d6eeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526020829052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff861690811790915590519091859173ffffffffffffffffffffffffffffffffffffffff8816917f92a1f7a41a7c585a8b09e25b195e225b1d43248daca46b0faf9e0792777a222991a450505050565b604080516020808252818301909252606091600091906020820181803683370190505090506000805b60208110156112cc576000858260208110611247576112476136de565b1a60f81b90507fff00000000000000000000000000000000000000000000000000000000000000811660000361127d57506112cc565b80848481518110611290576112906136de565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350506001918201910161122a565b5060008167ffffffffffffffff8111156112e8576112e861370d565b6040519080825280601f01601f191660200182016040528015611312576020820181803683370190505b50905060005b8281101561138657838181518110611332576113326136de565b602001015160f81c60f81b82828151811061134f5761134f6136de565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101611318565b50949350505050565b60408051808201909152600081526060602082015284516040805180820190915260008152606060208201528167ffffffffffffffff8111156113d4576113d461370d565b6040519080825280602002602001820160405280156113fd578160200160208202803683370190505b5060208201526040517fa2ea7c6e000000000000000000000000000000000000000000000000000000008152600481018990526000907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa15801561146f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114b59190810190613fc1565b80519091506114f0576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008367ffffffffffffffff81111561150b5761150b61370d565b6040519080825280602002602001820160405280156115aa57816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816115295790505b50905060008467ffffffffffffffff8111156115c8576115c861370d565b6040519080825280602002602001820160405280156115f1578160200160208202803683370190505b50905060005b85811015611a805760008b8281518110611613576116136136de565b60200260200101519050600067ffffffffffffffff16816020015167ffffffffffffffff161415801561165e57504267ffffffffffffffff16816020015167ffffffffffffffff1611155b15611695576040517f08e8b93700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84604001511580156116a8575080604001515b156116df576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052806000801b81526020018f81526020016117034290565b67ffffffffffffffff168152602001836020015167ffffffffffffffff168152602001600067ffffffffffffffff16815260200183606001518152602001836000015173ffffffffffffffffffffffffffffffffffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815260200183604001511515815260200183608001518152509050600080600090505b6117a58382612722565b600081815260326020526040902054909250156117c45760010161179b565b81835260008281526032602090815260409182902085518155908501516001820155908401516002820180546060870151608088015167ffffffffffffffff908116700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff92821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169190951617919091171691909117905560a0840151600382015560c084015160048201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560e0850151600583018054610100880151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff0000000000000000000000000000000000000000009091169290931691909117919091179055610120840151849190600682019061194490826140e7565b50505060608401511561199b57606084015160009081526032602052604090205461199b576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828786815181106119ae576119ae6136de565b60200260200101819052508360a001518686815181106119d0576119d06136de565b60200260200101818152505081896020015186815181106119f3576119f36136de565b6020026020010181815250508f8e73ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff167f8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b3585604051611a6391815260200190565b60405180910390a450505050611a798160010190565b90506115f7565b50611a9083838360008c8c612781565b845250919998505050505050505050565b606060008267ffffffffffffffff811115611abe57611abe61370d565b604051908082528060200260200182016040528015611ae7578160200160208202803683370190505b5090506000805b855181101561052e576000868281518110611b0b57611b0b6136de565b6020026020010151905060005b8151811015611b6457818181518110611b3357611b336136de565b6020026020010151858581518110611b4d57611b4d6136de565b602090810291909101015260019384019301611b18565b5050600101611aee565b6040517fa2ea7c6e0000000000000000000000000000000000000000000000000000000081526004810186905260009081907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa158015611bdc573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611c229190810190613fc1565b8051909150611c5d576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855160008167ffffffffffffffff811115611c7a57611c7a61370d565b604051908082528060200260200182016040528015611d1957816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611c985790505b50905060008267ffffffffffffffff811115611d3757611d3761370d565b604051908082528060200260200182016040528015611d60578160200160208202803683370190505b50905060005b8381101561218a5760008a8281518110611d8257611d826136de565b6020908102919091018101518051600090815260329092526040909120805491925090611ddb576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8c816001015414611e18576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015473ffffffffffffffffffffffffffffffffffffffff8c8116911614611e6e576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015474010000000000000000000000000000000000000000900460ff16611ec4576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002810154700100000000000000000000000000000000900467ffffffffffffffff1615611f1e576040517f905e710700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b426002820180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff811670010000000000000000000000000000000067ffffffffffffffff948516810291821793849055604080516101408101825287548152600188015460208201529386169286169290921791830191909152680100000000000000008304841660608301529091049091166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff161515610100820152600682018054839161012084019161202a90613d54565b80601f016020809104026020016040519081016040528092919081815260200182805461205690613d54565b80156120a35780601f10612078576101008083540402835291602001916120a3565b820191906000526020600020905b81548152906001019060200180831161208657829003601f168201915b5050505050815250508584815181106120be576120be6136de565b602002602001018190525081602001518484815181106120e0576120e06136de565b60200260200101818152505080600101548b73ffffffffffffffffffffffffffffffffffffffff168260040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167ff930a6e2523c9cc298691873087a740550b8fc85a0680830414c148ed927f615856000015160405161217891815260200190565b60405180910390a45050600101611d66565b5061219a84838360018b8b612781565b9a9950505050505050505050565b60008281526033602052604090205467ffffffffffffffff16156121f8576040517f2e26794600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526033602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051909184917f5aafceeb1c7ad58e4a84898bdee37c02c0fc46e7d24e6b60e8209449f183459f9190a35050565b6060816000036122ad57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156122d757806122c181614201565b91506122d09050600a83614268565b91506122b1565b60008167ffffffffffffffff8111156122f2576122f261370d565b6040519080825280601f01601f19166020018201604052801561231c576020820181803683370190505b5090505b841561239f57612331600183613a96565b915061233e600a8661427c565b612349906030614290565b60f81b81838151811061235e5761235e6136de565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612398600a86614268565b9450612320565b949350505050565b60208082015160408084015160608086015173ffffffffffffffffffffffffffffffffffffffff1660009081528086528381208054600181019091558751865187890151878901519589015160808a01518051908c01209851999a9799949895976124ad97612492977fdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de619791939290918c9101978852602088019690965273ffffffffffffffffffffffffffffffffffffffff94909416604087015267ffffffffffffffff9290921660608601521515608085015260a084015260c083015260e08201526101000190565b60405160208183030381529060405280519060200120612b5b565b905061252385606001518285602001518660400151876000015160405160200161250f93929190928352602083019190915260f81b7fff0000000000000000000000000000000000000000000000000000000000000016604082015260410190565b604051602081830303815290604052612b6e565b612559576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b60208181015160408084015160608086015173ffffffffffffffffffffffffffffffffffffffff1660009081528086528381208054600181019091558751865186517fa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a99650998101999099529588015291860193909352608085018190529293909291906124ad9060a001612492565b60003073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561265457507f000000000000000000000000000000000000000000000000000000000000000046145b1561267e57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60208083015160c084015160e0850151604080870151606088015161010089015160a08a01516101208b0151945160009961276399989796918c91016142a3565b60405160208183030381529060405280519060200120905092915050565b845160009060018190036127d9576127d188886000815181106127a6576127a66136de565b6020026020010151886000815181106127c1576127c16136de565b6020026020010151888888612d3d565b915050610697565b602088015173ffffffffffffffffffffffffffffffffffffffff811661286b5760005b8281101561285f57878181518110612816576128166136de565b6020026020010151600014612857576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016127fc565b50600092505050610697565b6000805b8381101561299557600089828151811061288b5761288b6136de565b602002602001015190508060001415801561291257508373ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129109190614381565b155b15612949576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87811115612983576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9687900396919091019060010161286f565b508615612a70576040517f88e5b2d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906388e5b2d99083906129f2908d908d9060040161439e565b60206040518083038185885af1158015612a10573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612a359190614381565b612a6b576040517fbf2f3a8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b3f565b6040517f91db0b7e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906391db0b7e908390612ac6908d908d9060040161439e565b60206040518083038185885af1158015612ae4573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612b099190614381565b612b3f576040517fe8bee83900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415612b4e57612b4e86613053565b9998505050505050505050565b6000610534612b686125ee565b83613066565b6000806000612b7d85856130a8565b90925090506000816004811115612b9657612b96614457565b148015612bce57508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b15612bde57600192505050612d36565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b8888604051602401612c13929190614486565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612c9c919061449f565b600060405180830381855afa9150503d8060008114612cd7576040519150601f19603f3d011682016040523d82523d6000602084013e612cdc565b606091505b5091509150818015612cef575080516020145b8015612d2f575080517f1626ba7e0000000000000000000000000000000000000000000000000000000090612d2d90830160209081019084016144b1565b145b9450505050505b9392505050565b602086015160009073ffffffffffffffffffffffffffffffffffffffff8116612da2578515612d98576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000915050610697565b8515801590612e1d57508073ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e1b9190614381565b155b15612e54576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83861115612e8e576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85840393508415612f6b576040517fe49617e100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e49617e1908890612eed908b90600401613617565b60206040518083038185885af1158015612f0b573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612f309190614381565b612f66576040517fccf3bb2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613038565b6040517fe60c350500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e60c3505908890612fbf908b90600401613617565b60206040518083038185885af1158015612fdd573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906130029190614381565b613038576040517fbd8ba84d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82156130475761304784613053565b50939695505050505050565b80156130635761306333826130ed565b50565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526022810183905260428101829052600090606201612763565b60008082516041036130de5760208301516040840151606085015160001a6130d28782858561324c565b945094505050506130e6565b506000905060025b9250929050565b8047101561315c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064015b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146131b6576040519150601f19603f3d011682016040523d82523d6000602084013e6131bb565b606091505b5050905080610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401613153565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613283575060009050600361335b565b8460ff16601b1415801561329b57508460ff16601c14155b156132ac575060009050600461335b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015613300573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166133545760006001925092505061335b565b9150600090505b94509492505050565b60008083601f84011261337657600080fd5b50813567ffffffffffffffff81111561338e57600080fd5b6020830191508360208260051b85010111156130e657600080fd5b600080602083850312156133bc57600080fd5b823567ffffffffffffffff8111156133d357600080fd5b6133df85828601613364565b90969095509350505050565b60005b838110156134065781810151838201526020016133ee565b50506000910152565b600081518084526134278160208601602086016133eb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d36602083018461340f565b73ffffffffffffffffffffffffffffffffffffffff8116811461306357600080fd5b80356134998161346c565b919050565b6000602082840312156134b057600080fd5b8135612d368161346c565b6020808252825182820181905260009190848201906040850190845b818110156134f3578351835292840192918401916001016134d7565b50909695505050505050565b60006060828403121561351157600080fd5b50919050565b60006020828403121561352957600080fd5b5035919050565b60006101408251845260208301516020850152604083015161355e604086018267ffffffffffffffff169052565b50606083015161357a606086018267ffffffffffffffff169052565b506080830151613596608086018267ffffffffffffffff169052565b5060a083015160a085015260c08301516135c860c086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e08301516135f060e086018273ffffffffffffffffffffffffffffffffffffffff169052565b5061010083810151151590850152610120808401518186018390526106978387018261340f565b602081526000612d366020830184613530565b6000806040838503121561363d57600080fd5b82356136488161346c565b946020939093013593505050565b60006020828403121561366857600080fd5b813567ffffffffffffffff81111561367f57600080fd5b820160c08185031215612d3657600080fd5b600060e0828403121561351157600080fd5b6000602082840312156136b557600080fd5b813567ffffffffffffffff8111156136cc57600080fd5b820160408185031215612d3657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261377057600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126137af57600080fd5b83018035915067ffffffffffffffff8211156137ca57600080fd5b6020019150600581901b36038213156130e657600080fd5b60405160c0810167ffffffffffffffff811182821017156138055761380561370d565b60405290565b6040516080810167ffffffffffffffff811182821017156138055761380561370d565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138755761387561370d565b604052919050565b600067ffffffffffffffff8211156138975761389761370d565b5060051b60200190565b801515811461306357600080fd5b8035613499816138a1565b600067ffffffffffffffff8211156138d4576138d461370d565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261391157600080fd5b813561392461391f826138ba565b61382e565b81815284602083860101111561393957600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561396857600080fd5b6139706137e2565b9050813561397d8161346c565b8152602082013567ffffffffffffffff808216821461399b57600080fd5b8160208401526139ad604085016138af565b60408401526060840135606084015260808401359150808211156139d057600080fd5b506139dd84828501613900565b60808301525060a082013560a082015292915050565b6000613a0161391f8461387d565b80848252602080830192508560051b850136811115613a1f57600080fd5b855b81811015613a5b57803567ffffffffffffffff811115613a415760008081fd5b613a4d36828a01613956565b865250938201938201613a21565b50919695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561053457610534613a67565b600060408284031215613abb57600080fd5b6040516040810181811067ffffffffffffffff82111715613ade57613ade61370d565b604052823581526020928301359281019290925250919050565b600060408284031215613b0a57600080fd5b612d368383613aa9565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613b4957600080fd5b83018035915067ffffffffffffffff821115613b6457600080fd5b6020019150600681901b36038213156130e657600080fd5b60008451613b8e8184602089016133eb565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551613bca816001850160208a016133eb565b60019201918201528351613be58160028401602088016133eb565b0160020195945050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261377057600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613c5b57600080fd5b83018035915067ffffffffffffffff821115613c7657600080fd5b60200191506060810236038213156130e657600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4183360301811261377057600080fd5b60006105343683613956565b600060608284031215613cdf57600080fd5b6040516060810181811067ffffffffffffffff82111715613d0257613d0261370d565b604052905080823560ff81168114613d1957600080fd5b8082525060208301356020820152604083013560408201525092915050565b600060608284031215613d4a57600080fd5b612d368383613ccd565b600181811c90821680613d6857607f821691505b602082108103613511577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060c08236031215613db357600080fd5b613dbb61380b565b82358152602083013567ffffffffffffffff811115613dd957600080fd5b613de536828601613956565b602083015250613df83660408501613ccd565b604082015260a0830135613e0b8161346c565b606082015292915050565b600082601f830112613e2757600080fd5b81356020613e3761391f8361387d565b82815260609283028501820192828201919087851115613e5657600080fd5b8387015b85811015613e7957613e6c8982613ccd565b8452928401928101613e5a565b5090979650505050505050565b600060808236031215613e9857600080fd5b613ea061380b565b8235815260208084013567ffffffffffffffff80821115613ec057600080fd5b9085019036601f830112613ed357600080fd5b8135613ee161391f8261387d565b81815260069190911b83018401908481019036831115613f0057600080fd5b938501935b82851015613f2957613f173686613aa9565b82528582019150604085019450613f05565b80868801525050506040860135925080831115613f4557600080fd5b5050613f5336828601613e16565b604083015250613e0b6060840161348e565b600060e08284031215613f7757600080fd5b613f7f61380b565b82358152613f908460208501613aa9565b6020820152613fa28460608501613ccd565b604082015260c0830135613fb58161346c565b60608201529392505050565b60006020808385031215613fd457600080fd5b825167ffffffffffffffff80821115613fec57600080fd5b908401906080828703121561400057600080fd5b61400861380b565b82518152838301516140198161346c565b81850152604083015161402b816138a1565b604082015260608301518281111561404257600080fd5b80840193505086601f84011261405757600080fd5b8251915061406761391f836138ba565b828152878584860101111561407b57600080fd5b61408a838683018787016133eb565b60608201529695505050505050565b601f82111561072057600081815260208120601f850160051c810160208610156140c05750805b601f850160051c820191505b818110156140df578281556001016140cc565b505050505050565b815167ffffffffffffffff8111156141015761410161370d565b6141158161410f8454613d54565b84614099565b602080601f83116001811461416857600084156141325750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556140df565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156141b557888601518255948401946001909101908401614196565b50858210156141f157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361423257614232613a67565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261427757614277614239565b500490565b60008261428b5761428b614239565b500690565b8082018082111561053457610534613a67565b89815260007fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808b60601b166020840152808a60601b166034840152507fffffffffffffffff000000000000000000000000000000000000000000000000808960c01b166048840152808860c01b1660508401525085151560f81b6058830152846059830152835161433c8160798501602088016133eb565b80830190507fffffffff000000000000000000000000000000000000000000000000000000008460e01b166079820152607d81019150509a9950505050505050505050565b60006020828403121561439357600080fd5b8151612d36816138a1565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b83811015614413577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552614401868351613530565b955093820193908201906001016143c7565b50508584038187015286518085528782019482019350915060005b8281101561444a5784518452938101939281019260010161442e565b5091979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061239f604083018461340f565b600082516137708184602087016133eb565b6000602082840312156144c357600080fd5b505191905056fea164736f6c6343000813000a" +var EASDeployedBin = "0x60806040526004361061018b5760003560e01c806395411525116100d6578063d45c44351161007f578063ed24911d11610059578063ed24911d146104c9578063f10b5cc8146104de578063f17325e71461050d57600080fd5b8063d45c443514610433578063e30bb5631461046a578063e71ff365146104a957600080fd5b8063b469318d116100b0578063b469318d14610386578063b83010d3146103e0578063cf190f341461041357600080fd5b80639541152514610333578063a3112a6414610346578063a6d4dbc71461037357600080fd5b806344adc90e116101385780634d003070116101125780634d003070146102de57806354fd4d50146102fe57806379f7573a1461031357600080fd5b806344adc90e1461029857806346926267146102b85780634cb7e9e5146102cb57600080fd5b806317d7de7c1161016957806317d7de7c146102205780632d0335ab146102425780633c0427151461028557600080fd5b80630eabf6601461019057806312b11a17146101a557806313893f61146101e7575b600080fd5b6101a361019e366004613643565b610520565b005b3480156101b157600080fd5b507ff83bb2b0ede93a840239f7e701a54d9bc35f03701f51ae153d601c6947ff3d3f5b6040519081526020015b60405180910390f35b3480156101f357600080fd5b50610207610202366004613643565b6106b7565b60405167ffffffffffffffff90911681526020016101de565b34801561022c57600080fd5b506102356106fc565b6040516101de91906136f3565b34801561024e57600080fd5b506101d461025d366004613738565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101d4610293366004613755565b61072c565b6102ab6102a6366004613643565b61082f565b6040516101de9190613790565b6101a36102c63660046137d4565b6109b0565b6101a36102d9366004613643565b610a34565b3480156102ea57600080fd5b506102076102f93660046137ec565b610b17565b34801561030a57600080fd5b50610235610b24565b34801561031f57600080fd5b506101a361032e3660046137ec565b610bc7565b6102ab610341366004613643565b610c5e565b34801561035257600080fd5b506103666103613660046137ec565b610ed1565b6040516101de91906138ec565b6101a36103813660046138ff565b611094565b34801561039257600080fd5b506102076103a1366004613912565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152603460209081526040808320938352929052205467ffffffffffffffff1690565b3480156103ec57600080fd5b507f2d4116d8c9824e4c316453e5c2843a1885580374159ce8768603c49085ef424c6101d4565b34801561041f57600080fd5b5061020761042e3660046137ec565b611139565b34801561043f57600080fd5b5061020761044e3660046137ec565b60009081526033602052604090205467ffffffffffffffff1690565b34801561047657600080fd5b506104996104853660046137ec565b600090815260326020526040902054151590565b60405190151581526020016101de565b3480156104b557600080fd5b506102076104c4366004613643565b611147565b3480156104d557600080fd5b506101d461117f565b3480156104ea57600080fd5b5060405173420000000000000000000000000000000000002081526020016101de565b6101d461051b36600461393e565b611189565b348160005b818110156106b0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82018114600086868481811061056657610566613979565b905060200281019061057891906139a8565b61058190613c3e565b602081015180519192509080158061059e57508260400151518114155b156105d5576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610679576106716040518060a001604052808660000151815260200185848151811061060a5761060a613979565b602002602001015181526020018660400151848151811061062d5761062d613979565b60200260200101518152602001866060015173ffffffffffffffffffffffffffffffffffffffff168152602001866080015167ffffffffffffffff16815250611247565b6001016105d8565b5061068f83600001518385606001518a88611434565b6106999088613d68565b9650505050506106a98160010190565b9050610525565b5050505050565b60004282825b818110156106f0576106e8338787848181106106db576106db613979565b9050602002013585611a63565b6001016106bd565b50909150505b92915050565b60606107277f0000000000000000000000000000000000000000000000000000000000000000611b62565b905090565b600061073f61073a83613e9d565b611cf0565b604080516001808252818301909252600091816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816107565790505090506107c46020840184613f18565b6107cd90613f4c565b816000815181106107e0576107e0613979565b602090810291909101015261080983358261080160c0870160a08801613738565b346001611e6d565b6020015160008151811061081f5761081f613979565b6020026020010151915050919050565b60608160008167ffffffffffffffff81111561084d5761084d6139e6565b60405190808252806020026020018201604052801561088057816020015b606081526020019060019003908161086b5790505b509050600034815b8481101561099a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85018114368989848181106108c8576108c8613979565b90506020028101906108da9190613f58565b90506108e96020820182613f8c565b9050600003610924576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061094982356109386020850185613f8c565b61094191613ff4565b338887611e6d565b80519091506109589086613d68565b9450806020015187858151811061097157610971613979565b6020026020010181905250806020015151860195505050506109938160010190565b9050610888565b506109a5838361257f565b979650505050505050565b604080516001808252818301909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816109c7579050509050610a0236839003830160208401614068565b81600081518110610a1557610a15613979565b6020908102919091010152610a2f82358233346001611434565b505050565b348160005b818110156106b0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201811436868684818110610a7957610a79613979565b9050602002810190610a8b9190613f58565b9050610af88135610a9f6020840184614084565b808060200260200160405190810160405280939291908181526020016000905b82821015610aeb57610adc60408302860136819003810190614068565b81526020019060010190610abf565b5050505050338886611434565b610b029086613d68565b94505050610b108160010190565b9050610a39565b6000426106f68382612669565b6060610b4f7f000000000000000000000000000000000000000000000000000000000000000061272b565b610b787f000000000000000000000000000000000000000000000000000000000000000061272b565b610ba17f000000000000000000000000000000000000000000000000000000000000000061272b565b604051602001610bb3939291906140ec565b604051602081830303815290604052905090565b33600090815260208190526040902054808211610c10576040517f756688fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152602081815260409182902084905581518381529081018490527f57b09af877df9068fd60a69d7b21f5576b8b38955812d6ae4ac52942f1e38fb7910160405180910390a15050565b60608160008167ffffffffffffffff811115610c7c57610c7c6139e6565b604051908082528060200260200182016040528015610caf57816020015b6060815260200190600190039081610c9a5790505b509050600034815b8481101561099a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8501811436898984818110610cf757610cf7613979565b9050602002810190610d0991906139a8565b9050366000610d1b6020840184613f8c565b909250905080801580610d3c5750610d366040850185614162565b90508114155b15610d73576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610e5457610e4c6040518060a0016040528087600001358152602001868685818110610da857610da8613979565b9050602002810190610dba9190613f18565b610dc390613f4c565b8152602001610dd56040890189614162565b85818110610de557610de5613979565b905060600201803603810190610dfb91906141c9565b8152602001610e106080890160608a01613738565b73ffffffffffffffffffffffffffffffffffffffff168152602001610e3b60a0890160808a016141e5565b67ffffffffffffffff169052611cf0565b600101610d76565b506000610e7d8535610e668587613ff4565b610e766080890160608a01613738565b8b8a611e6d565b8051909150610e8c9089613d68565b975080602001518a8881518110610ea557610ea5613979565b602002602001018190525080602001515189019850505050505050610eca8160010190565b9050610cb7565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082019290925261012081019190915260008281526032602090815260409182902082516101408101845281548152600182015492810192909252600281015467ffffffffffffffff808216948401949094526801000000000000000081048416606084015270010000000000000000000000000000000090049092166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff1615156101008201526006820180549192916101208401919061100b90614200565b80601f016020809104026020016040519081016040528092919081815260200182805461103790614200565b80156110845780601f1061105957610100808354040283529160200191611084565b820191906000526020600020905b81548152906001019060200180831161106757829003601f168201915b5050505050815250509050919050565b6110ab6110a63683900383018361424d565b611247565b604080516001808252818301909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816110c25790505090506110fd36839003830160208401614068565b8160008151811061111057611110613979565b6020908102919091010152610a2f82358261113160e0860160c08701613738565b346001611434565b6000426106f6338483611a63565b60004282825b818110156106f05761117786868381811061116a5761116a613979565b9050602002013584612669565b60010161114d565b6000610727612868565b604080516001808252818301909252600091829190816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816111a35790505090506112116020840184613f18565b61121a90613f4c565b8160008151811061122d5761122d613979565b602090810291909101015261080983358233346001611e6d565b608081015167ffffffffffffffff161580159061127b57504267ffffffffffffffff16816080015167ffffffffffffffff16105b156112b2576040517f1ab7da6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808201516040808401518451835184860151606088015173ffffffffffffffffffffffffffffffffffffffff166000908152968790529386208054959693959394611382947f2d4116d8c9824e4c316453e5c2843a1885580374159ce8768603c49085ef424c94939287611327836142bb565b909155506080808b015160408051602081019890985287019590955260608601939093529184015260a083015267ffffffffffffffff1660c082015260e0015b6040516020818303038152906040528051906020012061299c565b90506113f88460600151828460200151856040015186600001516040516020016113e493929190928352602083019190915260f81b7fff0000000000000000000000000000000000000000000000000000000000000016604082015260410190565b6040516020818303038152906040526129af565b61142e576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b6040517fa2ea7c6e0000000000000000000000000000000000000000000000000000000081526004810186905260009081907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa1580156114a2573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114e891908101906142f3565b8051909150611523576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855160008167ffffffffffffffff811115611540576115406139e6565b6040519080825280602002602001820160405280156115df57816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161155e5790505b50905060008267ffffffffffffffff8111156115fd576115fd6139e6565b604051908082528060200260200182016040528015611626578160200160208202803683370190505b50905060005b83811015611a455760008a828151811061164857611648613979565b60209081029190910181015180516000908152603290925260409091208054919250906116a1576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8c8160010154146116de576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015473ffffffffffffffffffffffffffffffffffffffff8c8116911614611734576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015474010000000000000000000000000000000000000000900460ff1661178a576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002810154700100000000000000000000000000000000900467ffffffffffffffff16156117e4576040517f905e710700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b426002820180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff811670010000000000000000000000000000000067ffffffffffffffff948516810291821793849055604080516101408101825287548152600188015460208201529386169286169290921791830191909152680100000000000000008304841660608301529091049091166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff16151561010082015260068201805483916101208401916118f090614200565b80601f016020809104026020016040519081016040528092919081815260200182805461191c90614200565b80156119695780601f1061193e57610100808354040283529160200191611969565b820191906000526020600020905b81548152906001019060200180831161194c57829003601f168201915b50505050508152505085848151811061198457611984613979565b602002602001018190525081602001518484815181106119a6576119a6613979565b6020026020010181815250508c8b73ffffffffffffffffffffffffffffffffffffffff168685815181106119dc576119dc613979565b602002602001015160c0015173ffffffffffffffffffffffffffffffffffffffff167ff930a6e2523c9cc298691873087a740550b8fc85a0680830414c148ed927f6158560000151604051611a3391815260200190565b60405180910390a4505060010161162c565b50611a5584838360018b8b612b7e565b9a9950505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152603460209081526040808320858452918290529091205467ffffffffffffffff1615611ad7576040517fec9d6eeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526020829052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff861690811790915590519091859173ffffffffffffffffffffffffffffffffffffffff8816917f92a1f7a41a7c585a8b09e25b195e225b1d43248daca46b0faf9e0792777a222991a450505050565b604080516020808252818301909252606091600091906020820181803683370190505090506000805b6020811015611c2d576000858260208110611ba857611ba8613979565b1a60f81b90507fff000000000000000000000000000000000000000000000000000000000000008116600003611bde5750611c2d565b80848481518110611bf157611bf1613979565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053505060019182019101611b8b565b5060008167ffffffffffffffff811115611c4957611c496139e6565b6040519080825280601f01601f191660200182016040528015611c73576020820181803683370190505b50905060005b82811015611ce757838181518110611c9357611c93613979565b602001015160f81c60f81b828281518110611cb057611cb0613979565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101611c79565b50949350505050565b608081015167ffffffffffffffff1615801590611d2457504267ffffffffffffffff16816080015167ffffffffffffffff16105b15611d5b576040517f1ab7da6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208082015160408084015184518351848601518486015160608088015160808901518051908b012060a08a0151928c015173ffffffffffffffffffffffffffffffffffffffff1660009081529a8b9052978a208054999a97999798611382987ff83bb2b0ede93a840239f7e701a54d9bc35f03701f51ae153d601c6947ff3d3f989796959491928b611ded836142bb565b909155506080808f015160408051602081019c909c528b019990995273ffffffffffffffffffffffffffffffffffffffff90971660608a015267ffffffffffffffff9586169689019690965292151560a088015260c087019190915260e08601526101008501526101208401919091521661014082015261016001611367565b60408051808201909152600081526060602082015284516040805180820190915260008152606060208201528167ffffffffffffffff811115611eb257611eb26139e6565b604051908082528060200260200182016040528015611edb578160200160208202803683370190505b5060208201526040517fa2ea7c6e000000000000000000000000000000000000000000000000000000008152600481018990526000907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa158015611f4d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611f9391908101906142f3565b8051909150611fce576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008367ffffffffffffffff811115611fe957611fe96139e6565b60405190808252806020026020018201604052801561208857816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816120075790505b50905060008467ffffffffffffffff8111156120a6576120a66139e6565b6040519080825280602002602001820160405280156120cf578160200160208202803683370190505b50905060005b8581101561255e5760008b82815181106120f1576120f1613979565b60200260200101519050600067ffffffffffffffff16816020015167ffffffffffffffff161415801561213c57504267ffffffffffffffff16816020015167ffffffffffffffff1611155b15612173576040517f08e8b93700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460400151158015612186575080604001515b156121bd576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052806000801b81526020018f81526020016121e14290565b67ffffffffffffffff168152602001836020015167ffffffffffffffff168152602001600067ffffffffffffffff16815260200183606001518152602001836000015173ffffffffffffffffffffffffffffffffffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815260200183604001511515815260200183608001518152509050600080600090505b6122838382612f6f565b600081815260326020526040902054909250156122a257600101612279565b81835260008281526032602090815260409182902085518155908501516001820155908401516002820180546060870151608088015167ffffffffffffffff908116700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff92821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169190951617919091171691909117905560a0840151600382015560c084015160048201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560e0850151600583018054610100880151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff000000000000000000000000000000000000000000909116929093169190911791909117905561012084015184919060068201906124229082614419565b505050606084015115612479576060840151600090815260326020526040902054612479576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8287868151811061248c5761248c613979565b60200260200101819052508360a001518686815181106124ae576124ae613979565b60200260200101818152505081896020015186815181106124d1576124d1613979565b6020026020010181815250508f8e73ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff167f8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b358560405161254191815260200190565b60405180910390a4505050506125578160010190565b90506120d5565b5061256e83838360008c8c612b7e565b845250919998505050505050505050565b606060008267ffffffffffffffff81111561259c5761259c6139e6565b6040519080825280602002602001820160405280156125c5578160200160208202803683370190505b508451909150600090815b8181101561265e5760008782815181106125ec576125ec613979565b6020026020010151905060008151905060005b8181101561264a5782818151811061261957612619613979565b602002602001015187878151811061263357612633613979565b6020908102919091010152600195860195016125ff565b5050506126578160010190565b90506125d0565b509195945050505050565b60008281526033602052604090205467ffffffffffffffff16156126b9576040517f2e26794600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526033602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051909184917f5aafceeb1c7ad58e4a84898bdee37c02c0fc46e7d24e6b60e8209449f183459f9190a35050565b60608160000361276e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156127985780612782816142bb565b91506127919050600a83614562565b9150612772565b60008167ffffffffffffffff8111156127b3576127b36139e6565b6040519080825280601f01601f1916602001820160405280156127dd576020820181803683370190505b5090505b8415612860576127f2600183613d68565b91506127ff600a86614576565b61280a90603061458a565b60f81b81838151811061281f5761281f613979565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612859600a86614562565b94506127e1565b949350505050565b60003073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156128ce57507f000000000000000000000000000000000000000000000000000000000000000046145b156128f857507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60006106f66129a9612868565b83612fce565b60008060006129be8585613010565b909250905060008160048111156129d7576129d761459d565b148015612a0f57508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b15612a1f57600192505050612b77565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b8888604051602401612a549291906145cc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612add91906145e5565b600060405180830381855afa9150503d8060008114612b18576040519150601f19603f3d011682016040523d82523d6000602084013e612b1d565b606091505b5091509150818015612b30575080516020145b8015612b70575080517f1626ba7e0000000000000000000000000000000000000000000000000000000090612b6e90830160209081019084016145f7565b145b9450505050505b9392505050565b84516000906001819003612bd657612bce8888600081518110612ba357612ba3613979565b602002602001015188600081518110612bbe57612bbe613979565b6020026020010151888888613055565b915050612f65565b602088015173ffffffffffffffffffffffffffffffffffffffff8116612c775760005b82811015612c5c57878181518110612c1357612c13613979565b6020026020010151600014612c54576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600101612bf9565b508315612c6c57612c6c85613374565b600092505050612f65565b6000808273ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cc5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce99190614610565b905060005b84811015612da65760008a8281518110612d0a57612d0a613979565b6020026020010151905080600003612d225750612d9e565b82612d59576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b88811115612d93576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b978890039792909201915b600101612cee565b508715612e81576040517f88e5b2d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416906388e5b2d9908490612e03908e908e9060040161462d565b60206040518083038185885af1158015612e21573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612e469190614610565b612e7c576040517fbf2f3a8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612f50565b6040517f91db0b7e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416906391db0b7e908490612ed7908e908e9060040161462d565b60206040518083038185885af1158015612ef5573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612f1a9190614610565b612f50576040517fe8bee83900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8515612f5f57612f5f87613374565b50925050505b9695505050505050565b60208083015160c084015160e0850151604080870151606088015161010089015160a08a01516101208b01519451600099612fb099989796918c91016146e6565b60405160208183030381529060405280519060200120905092915050565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526022810183905260428101829052600090606201612fb0565b60008082516041036130465760208301516040840151606085015160001a61303a87828585613387565b9450945050505061304e565b506000905060025b9250929050565b602086015160009073ffffffffffffffffffffffffffffffffffffffff81166130c95785156130b0576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82156130bf576130bf84613374565b6000915050612f65565b85156131b4578073ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561311a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061313e9190614610565b613174576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838611156131ae576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85840393505b841561328c576040517fe49617e100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e49617e190889061320e908b906004016138ec565b60206040518083038185885af115801561322c573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906132519190614610565b613287576040517fccf3bb2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613359565b6040517fe60c350500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e60c35059088906132e0908b906004016138ec565b60206040518083038185885af11580156132fe573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906133239190614610565b613359576040517fbd8ba84d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82156133685761336884613374565b50939695505050505050565b801561338457613384338261349f565b50565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156133be5750600090506003613496565b8460ff16601b141580156133d657508460ff16601c14155b156133e75750600090506004613496565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561343b573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661348f57600060019250925050613496565b9150600090505b94509492505050565b8047101561350e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064015b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114613568576040519150601f19603f3d011682016040523d82523d6000602084013e61356d565b606091505b5050905080610a2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401613505565b60008083601f84011261361057600080fd5b50813567ffffffffffffffff81111561362857600080fd5b6020830191508360208260051b850101111561304e57600080fd5b6000806020838503121561365657600080fd5b823567ffffffffffffffff81111561366d57600080fd5b613679858286016135fe565b90969095509350505050565b60005b838110156136a0578181015183820152602001613688565b50506000910152565b600081518084526136c1816020860160208601613685565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612b7760208301846136a9565b73ffffffffffffffffffffffffffffffffffffffff8116811461338457600080fd5b803561373381613706565b919050565b60006020828403121561374a57600080fd5b8135612b7781613706565b60006020828403121561376757600080fd5b813567ffffffffffffffff81111561377e57600080fd5b820160e08185031215612b7757600080fd5b6020808252825182820181905260009190848201906040850190845b818110156137c8578351835292840192918401916001016137ac565b50909695505050505050565b6000606082840312156137e657600080fd5b50919050565b6000602082840312156137fe57600080fd5b5035919050565b600061014082518452602083015160208501526040830151613833604086018267ffffffffffffffff169052565b50606083015161384f606086018267ffffffffffffffff169052565b50608083015161386b608086018267ffffffffffffffff169052565b5060a083015160a085015260c083015161389d60c086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e08301516138c560e086018273ffffffffffffffffffffffffffffffffffffffff169052565b506101008381015115159085015261012080840151818601839052612f65838701826136a9565b602081526000612b776020830184613805565b600061010082840312156137e657600080fd5b6000806040838503121561392557600080fd5b823561393081613706565b946020939093013593505050565b60006020828403121561395057600080fd5b813567ffffffffffffffff81111561396757600080fd5b820160408185031215612b7757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618336030181126139dc57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613a3857613a386139e6565b60405290565b60405160c0810167ffffffffffffffff81118282101715613a3857613a386139e6565b6040516080810167ffffffffffffffff81118282101715613a3857613a386139e6565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613acb57613acb6139e6565b604052919050565b600067ffffffffffffffff821115613aed57613aed6139e6565b5060051b60200190565b600060408284031215613b0957600080fd5b6040516040810181811067ffffffffffffffff82111715613b2c57613b2c6139e6565b604052823581526020928301359281019290925250919050565b600060608284031215613b5857600080fd5b6040516060810181811067ffffffffffffffff82111715613b7b57613b7b6139e6565b604052905080823560ff81168114613b9257600080fd5b8082525060208301356020820152604083013560408201525092915050565b600082601f830112613bc257600080fd5b81356020613bd7613bd283613ad3565b613a84565b82815260609283028501820192828201919087851115613bf657600080fd5b8387015b85811015613c1957613c0c8982613b46565b8452928401928101613bfa565b5090979650505050505050565b803567ffffffffffffffff8116811461373357600080fd5b600060a08236031215613c5057600080fd5b613c58613a15565b8235815260208084013567ffffffffffffffff80821115613c7857600080fd5b9085019036601f830112613c8b57600080fd5b8135613c99613bd282613ad3565b81815260069190911b83018401908481019036831115613cb857600080fd5b938501935b82851015613ce157613ccf3686613af7565b82528582019150604085019450613cbd565b80868801525050506040860135925080831115613cfd57600080fd5b5050613d0b36828601613bb1565b604083015250613d1d60608401613728565b6060820152613d2e60808401613c26565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156106f6576106f6613d39565b801515811461338457600080fd5b600067ffffffffffffffff821115613da357613da36139e6565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600060c08284031215613de157600080fd5b613de9613a3e565b90508135613df681613706565b81526020613e05838201613c26565b818301526040830135613e1781613d7b565b604083015260608381013590830152608083013567ffffffffffffffff811115613e4057600080fd5b8301601f81018513613e5157600080fd5b8035613e5f613bd282613d89565b8181528684838501011115613e7357600080fd5b818484018583013760008483830101528060808601525050505060a082013560a082015292915050565b600060e08236031215613eaf57600080fd5b613eb7613a15565b82358152602083013567ffffffffffffffff811115613ed557600080fd5b613ee136828601613dcf565b602083015250613ef43660408501613b46565b604082015260a0830135613f0781613706565b6060820152613d2e60c08401613c26565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff418336030181126139dc57600080fd5b60006106f63683613dcf565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126139dc57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613fc157600080fd5b83018035915067ffffffffffffffff821115613fdc57600080fd5b6020019150600581901b360382131561304e57600080fd5b6000614002613bd284613ad3565b80848252602080830192508560051b85013681111561402057600080fd5b855b8181101561405c57803567ffffffffffffffff8111156140425760008081fd5b61404e36828a01613dcf565b865250938201938201614022565b50919695505050505050565b60006040828403121561407a57600080fd5b612b778383613af7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126140b957600080fd5b83018035915067ffffffffffffffff8211156140d457600080fd5b6020019150600681901b360382131561304e57600080fd5b600084516140fe818460208901613685565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161413a816001850160208a01613685565b60019201918201528351614155816002840160208801613685565b0160020195945050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261419757600080fd5b83018035915067ffffffffffffffff8211156141b257600080fd5b602001915060608102360382131561304e57600080fd5b6000606082840312156141db57600080fd5b612b778383613b46565b6000602082840312156141f757600080fd5b612b7782613c26565b600181811c9082168061421457607f821691505b6020821081036137e6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000610100828403121561426057600080fd5b614268613a15565b823581526142798460208501613af7565b602082015261428b8460608501613b46565b604082015260c083013561429e81613706565b60608201526142af60e08401613c26565b60808201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036142ec576142ec613d39565b5060010190565b6000602080838503121561430657600080fd5b825167ffffffffffffffff8082111561431e57600080fd5b908401906080828703121561433257600080fd5b61433a613a61565b825181528383015161434b81613706565b81850152604083015161435d81613d7b565b604082015260608301518281111561437457600080fd5b80840193505086601f84011261438957600080fd5b82519150614399613bd283613d89565b82815287858486010111156143ad57600080fd5b6143bc83868301878701613685565b60608201529695505050505050565b601f821115610a2f57600081815260208120601f850160051c810160208610156143f25750805b601f850160051c820191505b81811015614411578281556001016143fe565b505050505050565b815167ffffffffffffffff811115614433576144336139e6565b614447816144418454614200565b846143cb565b602080601f83116001811461449a57600084156144645750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555614411565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156144e7578886015182559484019460019091019084016144c8565b508582101561452357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261457157614571614533565b500490565b60008261458557614585614533565b500690565b808201808211156106f6576106f6613d39565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061286060408301846136a9565b600082516139dc818460208701613685565b60006020828403121561460957600080fd5b5051919050565b60006020828403121561462257600080fd5b8151612b7781613d7b565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b838110156146a2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552614690868351613805565b95509382019390820190600101614656565b50508584038187015286518085528782019482019350915060005b828110156146d9578451845293810193928101926001016146bd565b5091979650505050505050565b89815260007fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808b60601b166020840152808a60601b166034840152507fffffffffffffffff000000000000000000000000000000000000000000000000808960c01b166048840152808860c01b1660508401525085151560f81b6058830152846059830152835161477f816079850160208801613685565b80830190507fffffffff000000000000000000000000000000000000000000000000000000008460e01b166079820152607d81019150509a995050505050505050505056fea164736f6c6343000813000a" func init() { if err := json.Unmarshal([]byte(EASStorageLayoutJSON), EASStorageLayout); err != nil { diff --git a/op-bindings/bindings/schemaregistry.go b/op-bindings/bindings/schemaregistry.go index bf65f116c..6f0004363 100644 --- a/op-bindings/bindings/schemaregistry.go +++ b/op-bindings/bindings/schemaregistry.go @@ -38,8 +38,8 @@ type SchemaRecord struct { // SchemaRegistryMetaData contains all meta data concerning the SchemaRegistry contract. var SchemaRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyExists\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"registerer\",\"type\":\"address\"}],\"name\":\"Registered\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"name\":\"getSchema\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"contractISchemaResolver\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"schema\",\"type\":\"string\"}],\"internalType\":\"structSchemaRecord\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"schema\",\"type\":\"string\"},{\"internalType\":\"contractISchemaResolver\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"}],\"name\":\"register\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60e060405234801561001057600080fd5b506001608052600060a052600360c05260805160a05160c051610b1661004c600039600060fe0152600060d50152600060ac0152610b166000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806360d7a27814610064578063a2ea7c6e14610085575b600080fd5b61004e6100a5565b60405161005b9190610604565b60405180910390f35b61007761007236600461061e565b610148565b60405190815260200161005b565b6100986100933660046106d0565b6102f1565b60405161005b91906106e9565b60606100d07f0000000000000000000000000000000000000000000000000000000000000000610419565b6100f97f0000000000000000000000000000000000000000000000000000000000000000610419565b6101227f0000000000000000000000000000000000000000000000000000000000000000610419565b6040516020016101349392919061073a565b604051602081830303815290604052905090565b60008060405180608001604052806000801b81526020018573ffffffffffffffffffffffffffffffffffffffff168152602001841515815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525092935091506101ca905082610556565b60008181526020819052604090205490915015610213576040517f23369fa600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80825260008181526020818152604091829020845181559084015160018201805493860151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090941673ffffffffffffffffffffffffffffffffffffffff9092169190911792909217909155606083015183919060028201906102af9082610881565b50506040513381528291507f7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c9060200160405180910390a29695505050505050565b604080516080810182526000808252602082018190529181019190915260608082015260008281526020818152604091829020825160808101845281548152600182015473ffffffffffffffffffffffffffffffffffffffff8116938201939093527401000000000000000000000000000000000000000090920460ff16151592820192909252600282018054919291606084019190610390906107df565b80601f01602080910402602001604051908101604052809291908181526020018280546103bc906107df565b80156104095780601f106103de57610100808354040283529160200191610409565b820191906000526020600020905b8154815290600101906020018083116103ec57829003601f168201915b5050505050815250509050919050565b60608160000361045c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104865780610470816109ca565b915061047f9050600a83610a31565b9150610460565b60008167ffffffffffffffff8111156104a1576104a16107b0565b6040519080825280601f01601f1916602001820160405280156104cb576020820181803683370190505b5090505b841561054e576104e0600183610a45565b91506104ed600a86610a5e565b6104f8906030610a72565b60f81b81838151811061050d5761050d610a85565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610547600a86610a31565b94506104cf565b949350505050565b600081606001518260200151836040015160405160200161057993929190610ab4565b604051602081830303815290604052805190602001209050919050565b60005b838110156105b1578181015183820152602001610599565b50506000910152565b600081518084526105d2816020860160208601610596565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061061760208301846105ba565b9392505050565b6000806000806060858703121561063457600080fd5b843567ffffffffffffffff8082111561064c57600080fd5b818701915087601f83011261066057600080fd5b81358181111561066f57600080fd5b88602082850101111561068157600080fd5b6020928301965094505085013573ffffffffffffffffffffffffffffffffffffffff811681146106b057600080fd5b9150604085013580151581146106c557600080fd5b939692955090935050565b6000602082840312156106e257600080fd5b5035919050565b602081528151602082015273ffffffffffffffffffffffffffffffffffffffff60208301511660408201526040820151151560608201526000606083015160808084015261054e60a08401826105ba565b6000845161074c818460208901610596565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610788816001850160208a01610596565b600192019182015283516107a3816002840160208801610596565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600181811c908216806107f357607f821691505b60208210810361082c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561087c57600081815260208120601f850160051c810160208610156108595750805b601f850160051c820191505b8181101561087857828155600101610865565b5050505b505050565b815167ffffffffffffffff81111561089b5761089b6107b0565b6108af816108a984546107df565b84610832565b602080601f83116001811461090257600084156108cc5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610878565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561094f57888601518255948401946001909101908401610930565b508582101561098b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109fb576109fb61099b565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a4057610a40610a02565b500490565b81810381811115610a5857610a5861099b565b92915050565b600082610a6d57610a6d610a02565b500690565b80820180821115610a5857610a5861099b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008451610ac6818460208901610596565b60609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190930190815290151560f81b60148201526015019291505056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyExists\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"registerer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"contractISchemaResolver\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"schema\",\"type\":\"string\"}],\"indexed\":false,\"internalType\":\"structSchemaRecord\",\"name\":\"schema\",\"type\":\"tuple\"}],\"name\":\"Registered\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"name\":\"getSchema\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"contractISchemaResolver\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"schema\",\"type\":\"string\"}],\"internalType\":\"structSchemaRecord\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"schema\",\"type\":\"string\"},{\"internalType\":\"contractISchemaResolver\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"}],\"name\":\"register\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60e060405234801561001057600080fd5b506001608052600260a052600060c05260805160a05160c051610b3161004c600039600060fe0152600060d50152600060ac0152610b316000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806360d7a27814610064578063a2ea7c6e14610085575b600080fd5b61004e6100a5565b60405161005b919061061f565b60405180910390f35b610077610072366004610639565b610148565b60405190815260200161005b565b6100986100933660046106eb565b61030c565b60405161005b9190610704565b60606100d07f0000000000000000000000000000000000000000000000000000000000000000610434565b6100f97f0000000000000000000000000000000000000000000000000000000000000000610434565b6101227f0000000000000000000000000000000000000000000000000000000000000000610434565b60405160200161013493929190610755565b604051602081830303815290604052905090565b60008060405180608001604052806000801b81526020018573ffffffffffffffffffffffffffffffffffffffff168152602001841515815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525092935091506101ca905082610571565b60008181526020819052604090205490915015610213576040517f23369fa600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80825260008181526020818152604091829020845181559084015160018201805493860151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090941673ffffffffffffffffffffffffffffffffffffffff9092169190911792909217909155606083015183919060028201906102af908261089c565b509050503373ffffffffffffffffffffffffffffffffffffffff16817fd0b86852e21f9e5fa4bc3b0cff9757ffe243d50c4b43968a42202153d651ea5e846040516102fa9190610704565b60405180910390a39695505050505050565b604080516080810182526000808252602082018190529181019190915260608082015260008281526020818152604091829020825160808101845281548152600182015473ffffffffffffffffffffffffffffffffffffffff8116938201939093527401000000000000000000000000000000000000000090920460ff161515928201929092526002820180549192916060840191906103ab906107fa565b80601f01602080910402602001604051908101604052809291908181526020018280546103d7906107fa565b80156104245780601f106103f957610100808354040283529160200191610424565b820191906000526020600020905b81548152906001019060200180831161040757829003601f168201915b5050505050815250509050919050565b60608160000361047757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104a1578061048b816109e5565b915061049a9050600a83610a4c565b915061047b565b60008167ffffffffffffffff8111156104bc576104bc6107cb565b6040519080825280601f01601f1916602001820160405280156104e6576020820181803683370190505b5090505b8415610569576104fb600183610a60565b9150610508600a86610a79565b610513906030610a8d565b60f81b81838151811061052857610528610aa0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610562600a86610a4c565b94506104ea565b949350505050565b600081606001518260200151836040015160405160200161059493929190610acf565b604051602081830303815290604052805190602001209050919050565b60005b838110156105cc5781810151838201526020016105b4565b50506000910152565b600081518084526105ed8160208601602086016105b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061063260208301846105d5565b9392505050565b6000806000806060858703121561064f57600080fd5b843567ffffffffffffffff8082111561066757600080fd5b818701915087601f83011261067b57600080fd5b81358181111561068a57600080fd5b88602082850101111561069c57600080fd5b6020928301965094505085013573ffffffffffffffffffffffffffffffffffffffff811681146106cb57600080fd5b9150604085013580151581146106e057600080fd5b939692955090935050565b6000602082840312156106fd57600080fd5b5035919050565b602081528151602082015273ffffffffffffffffffffffffffffffffffffffff60208301511660408201526040820151151560608201526000606083015160808084015261056960a08401826105d5565b600084516107678184602089016105b1565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516107a3816001850160208a016105b1565b600192019182015283516107be8160028401602088016105b1565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600181811c9082168061080e57607f821691505b602082108103610847577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561089757600081815260208120601f850160051c810160208610156108745750805b601f850160051c820191505b8181101561089357828155600101610880565b5050505b505050565b815167ffffffffffffffff8111156108b6576108b66107cb565b6108ca816108c484546107fa565b8461084d565b602080601f83116001811461091d57600084156108e75750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610893565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561096a5788860151825594840194600190910190840161094b565b50858210156109a657878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610a1657610a166109b6565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a5b57610a5b610a1d565b500490565b81810381811115610a7357610a736109b6565b92915050565b600082610a8857610a88610a1d565b500690565b80820180821115610a7357610a736109b6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008451610ae18184602089016105b1565b60609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190930190815290151560f81b60148201526015019291505056fea164736f6c6343000813000a", } // SchemaRegistryABI is the input ABI used to generate the binding from. @@ -363,37 +363,46 @@ func (it *SchemaRegistryRegisteredIterator) Close() error { type SchemaRegistryRegistered struct { Uid [32]byte Registerer common.Address + Schema SchemaRecord Raw types.Log // Blockchain specific contextual infos } -// FilterRegistered is a free log retrieval operation binding the contract event 0x7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c. +// FilterRegistered is a free log retrieval operation binding the contract event 0xd0b86852e21f9e5fa4bc3b0cff9757ffe243d50c4b43968a42202153d651ea5e. // -// Solidity: event Registered(bytes32 indexed uid, address registerer) -func (_SchemaRegistry *SchemaRegistryFilterer) FilterRegistered(opts *bind.FilterOpts, uid [][32]byte) (*SchemaRegistryRegisteredIterator, error) { +// Solidity: event Registered(bytes32 indexed uid, address indexed registerer, (bytes32,address,bool,string) schema) +func (_SchemaRegistry *SchemaRegistryFilterer) FilterRegistered(opts *bind.FilterOpts, uid [][32]byte, registerer []common.Address) (*SchemaRegistryRegisteredIterator, error) { var uidRule []interface{} for _, uidItem := range uid { uidRule = append(uidRule, uidItem) } + var registererRule []interface{} + for _, registererItem := range registerer { + registererRule = append(registererRule, registererItem) + } - logs, sub, err := _SchemaRegistry.contract.FilterLogs(opts, "Registered", uidRule) + logs, sub, err := _SchemaRegistry.contract.FilterLogs(opts, "Registered", uidRule, registererRule) if err != nil { return nil, err } return &SchemaRegistryRegisteredIterator{contract: _SchemaRegistry.contract, event: "Registered", logs: logs, sub: sub}, nil } -// WatchRegistered is a free log subscription operation binding the contract event 0x7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c. +// WatchRegistered is a free log subscription operation binding the contract event 0xd0b86852e21f9e5fa4bc3b0cff9757ffe243d50c4b43968a42202153d651ea5e. // -// Solidity: event Registered(bytes32 indexed uid, address registerer) -func (_SchemaRegistry *SchemaRegistryFilterer) WatchRegistered(opts *bind.WatchOpts, sink chan<- *SchemaRegistryRegistered, uid [][32]byte) (event.Subscription, error) { +// Solidity: event Registered(bytes32 indexed uid, address indexed registerer, (bytes32,address,bool,string) schema) +func (_SchemaRegistry *SchemaRegistryFilterer) WatchRegistered(opts *bind.WatchOpts, sink chan<- *SchemaRegistryRegistered, uid [][32]byte, registerer []common.Address) (event.Subscription, error) { var uidRule []interface{} for _, uidItem := range uid { uidRule = append(uidRule, uidItem) } + var registererRule []interface{} + for _, registererItem := range registerer { + registererRule = append(registererRule, registererItem) + } - logs, sub, err := _SchemaRegistry.contract.WatchLogs(opts, "Registered", uidRule) + logs, sub, err := _SchemaRegistry.contract.WatchLogs(opts, "Registered", uidRule, registererRule) if err != nil { return nil, err } @@ -425,9 +434,9 @@ func (_SchemaRegistry *SchemaRegistryFilterer) WatchRegistered(opts *bind.WatchO }), nil } -// ParseRegistered is a log parse operation binding the contract event 0x7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c. +// ParseRegistered is a log parse operation binding the contract event 0xd0b86852e21f9e5fa4bc3b0cff9757ffe243d50c4b43968a42202153d651ea5e. // -// Solidity: event Registered(bytes32 indexed uid, address registerer) +// Solidity: event Registered(bytes32 indexed uid, address indexed registerer, (bytes32,address,bool,string) schema) func (_SchemaRegistry *SchemaRegistryFilterer) ParseRegistered(log types.Log) (*SchemaRegistryRegistered, error) { event := new(SchemaRegistryRegistered) if err := _SchemaRegistry.contract.UnpackLog(event, "Registered", log); err != nil { diff --git a/op-bindings/bindings/schemaregistry_more.go b/op-bindings/bindings/schemaregistry_more.go index af2eae44f..6b68b5332 100644 --- a/op-bindings/bindings/schemaregistry_more.go +++ b/op-bindings/bindings/schemaregistry_more.go @@ -13,7 +13,7 @@ const SchemaRegistryStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contrac var SchemaRegistryStorageLayout = new(solc.StorageLayout) -var SchemaRegistryDeployedBin = "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806360d7a27814610064578063a2ea7c6e14610085575b600080fd5b61004e6100a5565b60405161005b9190610604565b60405180910390f35b61007761007236600461061e565b610148565b60405190815260200161005b565b6100986100933660046106d0565b6102f1565b60405161005b91906106e9565b60606100d07f0000000000000000000000000000000000000000000000000000000000000000610419565b6100f97f0000000000000000000000000000000000000000000000000000000000000000610419565b6101227f0000000000000000000000000000000000000000000000000000000000000000610419565b6040516020016101349392919061073a565b604051602081830303815290604052905090565b60008060405180608001604052806000801b81526020018573ffffffffffffffffffffffffffffffffffffffff168152602001841515815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525092935091506101ca905082610556565b60008181526020819052604090205490915015610213576040517f23369fa600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80825260008181526020818152604091829020845181559084015160018201805493860151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090941673ffffffffffffffffffffffffffffffffffffffff9092169190911792909217909155606083015183919060028201906102af9082610881565b50506040513381528291507f7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c9060200160405180910390a29695505050505050565b604080516080810182526000808252602082018190529181019190915260608082015260008281526020818152604091829020825160808101845281548152600182015473ffffffffffffffffffffffffffffffffffffffff8116938201939093527401000000000000000000000000000000000000000090920460ff16151592820192909252600282018054919291606084019190610390906107df565b80601f01602080910402602001604051908101604052809291908181526020018280546103bc906107df565b80156104095780601f106103de57610100808354040283529160200191610409565b820191906000526020600020905b8154815290600101906020018083116103ec57829003601f168201915b5050505050815250509050919050565b60608160000361045c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104865780610470816109ca565b915061047f9050600a83610a31565b9150610460565b60008167ffffffffffffffff8111156104a1576104a16107b0565b6040519080825280601f01601f1916602001820160405280156104cb576020820181803683370190505b5090505b841561054e576104e0600183610a45565b91506104ed600a86610a5e565b6104f8906030610a72565b60f81b81838151811061050d5761050d610a85565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610547600a86610a31565b94506104cf565b949350505050565b600081606001518260200151836040015160405160200161057993929190610ab4565b604051602081830303815290604052805190602001209050919050565b60005b838110156105b1578181015183820152602001610599565b50506000910152565b600081518084526105d2816020860160208601610596565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061061760208301846105ba565b9392505050565b6000806000806060858703121561063457600080fd5b843567ffffffffffffffff8082111561064c57600080fd5b818701915087601f83011261066057600080fd5b81358181111561066f57600080fd5b88602082850101111561068157600080fd5b6020928301965094505085013573ffffffffffffffffffffffffffffffffffffffff811681146106b057600080fd5b9150604085013580151581146106c557600080fd5b939692955090935050565b6000602082840312156106e257600080fd5b5035919050565b602081528151602082015273ffffffffffffffffffffffffffffffffffffffff60208301511660408201526040820151151560608201526000606083015160808084015261054e60a08401826105ba565b6000845161074c818460208901610596565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610788816001850160208a01610596565b600192019182015283516107a3816002840160208801610596565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600181811c908216806107f357607f821691505b60208210810361082c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561087c57600081815260208120601f850160051c810160208610156108595750805b601f850160051c820191505b8181101561087857828155600101610865565b5050505b505050565b815167ffffffffffffffff81111561089b5761089b6107b0565b6108af816108a984546107df565b84610832565b602080601f83116001811461090257600084156108cc5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610878565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561094f57888601518255948401946001909101908401610930565b508582101561098b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109fb576109fb61099b565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a4057610a40610a02565b500490565b81810381811115610a5857610a5861099b565b92915050565b600082610a6d57610a6d610a02565b500690565b80820180821115610a5857610a5861099b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008451610ac6818460208901610596565b60609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190930190815290151560f81b60148201526015019291505056fea164736f6c6343000813000a" +var SchemaRegistryDeployedBin = "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806360d7a27814610064578063a2ea7c6e14610085575b600080fd5b61004e6100a5565b60405161005b919061061f565b60405180910390f35b610077610072366004610639565b610148565b60405190815260200161005b565b6100986100933660046106eb565b61030c565b60405161005b9190610704565b60606100d07f0000000000000000000000000000000000000000000000000000000000000000610434565b6100f97f0000000000000000000000000000000000000000000000000000000000000000610434565b6101227f0000000000000000000000000000000000000000000000000000000000000000610434565b60405160200161013493929190610755565b604051602081830303815290604052905090565b60008060405180608001604052806000801b81526020018573ffffffffffffffffffffffffffffffffffffffff168152602001841515815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525092935091506101ca905082610571565b60008181526020819052604090205490915015610213576040517f23369fa600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80825260008181526020818152604091829020845181559084015160018201805493860151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090941673ffffffffffffffffffffffffffffffffffffffff9092169190911792909217909155606083015183919060028201906102af908261089c565b509050503373ffffffffffffffffffffffffffffffffffffffff16817fd0b86852e21f9e5fa4bc3b0cff9757ffe243d50c4b43968a42202153d651ea5e846040516102fa9190610704565b60405180910390a39695505050505050565b604080516080810182526000808252602082018190529181019190915260608082015260008281526020818152604091829020825160808101845281548152600182015473ffffffffffffffffffffffffffffffffffffffff8116938201939093527401000000000000000000000000000000000000000090920460ff161515928201929092526002820180549192916060840191906103ab906107fa565b80601f01602080910402602001604051908101604052809291908181526020018280546103d7906107fa565b80156104245780601f106103f957610100808354040283529160200191610424565b820191906000526020600020905b81548152906001019060200180831161040757829003601f168201915b5050505050815250509050919050565b60608160000361047757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104a1578061048b816109e5565b915061049a9050600a83610a4c565b915061047b565b60008167ffffffffffffffff8111156104bc576104bc6107cb565b6040519080825280601f01601f1916602001820160405280156104e6576020820181803683370190505b5090505b8415610569576104fb600183610a60565b9150610508600a86610a79565b610513906030610a8d565b60f81b81838151811061052857610528610aa0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610562600a86610a4c565b94506104ea565b949350505050565b600081606001518260200151836040015160405160200161059493929190610acf565b604051602081830303815290604052805190602001209050919050565b60005b838110156105cc5781810151838201526020016105b4565b50506000910152565b600081518084526105ed8160208601602086016105b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061063260208301846105d5565b9392505050565b6000806000806060858703121561064f57600080fd5b843567ffffffffffffffff8082111561066757600080fd5b818701915087601f83011261067b57600080fd5b81358181111561068a57600080fd5b88602082850101111561069c57600080fd5b6020928301965094505085013573ffffffffffffffffffffffffffffffffffffffff811681146106cb57600080fd5b9150604085013580151581146106e057600080fd5b939692955090935050565b6000602082840312156106fd57600080fd5b5035919050565b602081528151602082015273ffffffffffffffffffffffffffffffffffffffff60208301511660408201526040820151151560608201526000606083015160808084015261056960a08401826105d5565b600084516107678184602089016105b1565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516107a3816001850160208a016105b1565b600192019182015283516107be8160028401602088016105b1565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600181811c9082168061080e57607f821691505b602082108103610847577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561089757600081815260208120601f850160051c810160208610156108745750805b601f850160051c820191505b8181101561089357828155600101610880565b5050505b505050565b815167ffffffffffffffff8111156108b6576108b66107cb565b6108ca816108c484546107fa565b8461084d565b602080601f83116001811461091d57600084156108e75750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610893565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561096a5788860151825594840194600190910190840161094b565b50858210156109a657878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610a1657610a166109b6565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a5b57610a5b610a1d565b500490565b81810381811115610a7357610a736109b6565b92915050565b600082610a8857610a88610a1d565b500690565b80820180821115610a7357610a736109b6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008451610ae18184602089016105b1565b60609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190930190815290151560f81b60148201526015019291505056fea164736f6c6343000813000a" func init() { if err := json.Unmarshal([]byte(SchemaRegistryStorageLayoutJSON), SchemaRegistryStorageLayout); err != nil { diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index b99681585..559f2e32c 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -1,6 +1,6 @@ { - "src/EAS/EAS.sol": "0x00862a9f0088230acc1f5c5d0e4041bcc28cb3b3675d0eb7e1cceee7cf9502f8", - "src/EAS/SchemaRegistry.sol": "0xf1cd4415f85775124c226e1a356d8b9b5126b9e9bdbe5aebb3876d46f8e1217a", + "src/EAS/EAS.sol": "0x1acb25751a1206eb859cc5fcf934da2f84cfb907b8e8951d86fc4e43c53a7303", + "src/EAS/SchemaRegistry.sol": "0x305f3afed2e337cd70aac70fc202e6503b947b0a31e0d4e18c49486eeb635bb5", "src/L1/L1CrossDomainMessenger.sol": "0x0e663b5d608b07cf278b94b1eeb3202abc01bea6b5905a3869010353df33ad1a", "src/L1/L1ERC721Bridge.sol": "0xbb10b777d1cd36ef98b53df6675f37a20b14a9a82b174f0d8f8872eedca65f17", "src/L1/L1StandardBridge.sol": "0xbd7b303cefe46bc14bf1a2b81e5702ff45ce9c5257524e59778e11c75f7f5bdc", diff --git a/packages/contracts-bedrock/src/EAS/Common.sol b/packages/contracts-bedrock/src/EAS/Common.sol index 22f4cf155..2e361a59e 100644 --- a/packages/contracts-bedrock/src/EAS/Common.sol +++ b/packages/contracts-bedrock/src/EAS/Common.sol @@ -8,6 +8,7 @@ bytes32 constant EMPTY_UID = 0; uint64 constant NO_EXPIRATION_TIME = 0; error AccessDenied(); +error DeadlineExpired(); error InvalidEAS(); error InvalidLength(); error InvalidSignature(); diff --git a/packages/contracts-bedrock/src/EAS/EAS.sol b/packages/contracts-bedrock/src/EAS/EAS.sol index 3bc709d83..8fc4f9ffa 100644 --- a/packages/contracts-bedrock/src/EAS/EAS.sol +++ b/packages/contracts-bedrock/src/EAS/EAS.sol @@ -80,8 +80,8 @@ contract EAS is IEAS, Semver, EIP1271Verifier { uint256[MAX_GAP - 3] private __gap; /// @dev Creates a new EAS instance. - /// @custom:semver 1.1.0 - constructor() Semver(1, 1, 0) EIP1271Verifier("EAS", "1.0.1") { } + /// @custom:semver 1.2.0 + constructor() Semver(1, 2, 0) EIP1271Verifier("EAS", "1.2.0") { } /// @inheritdoc IEAS function getSchemaRegistry() external pure returns (ISchemaRegistry) { @@ -90,9 +90,10 @@ contract EAS is IEAS, Semver, EIP1271Verifier { /// @inheritdoc IEAS function attest(AttestationRequest calldata request) external payable returns (bytes32) { - AttestationRequestData[] memory requests = new AttestationRequestData[](1); - requests[0] = request.data; - return _attest(request.schema, requests, msg.sender, msg.value, true).uids[0]; + AttestationRequestData[] memory data = new AttestationRequestData[](1); + data[0] = request.data; + + return _attest(request.schema, data, msg.sender, msg.value, true).uids[0]; } /// @inheritdoc IEAS @@ -116,7 +117,8 @@ contract EAS is IEAS, Semver, EIP1271Verifier { { // Since a multi-attest call is going to make multiple attestations for multiple schemas, we'd need to collect // all the returned UIDs into a single list. - bytes32[][] memory totalUids = new bytes32[][](multiRequests.length); + uint256 length = multiRequests.length; + bytes32[][] memory totalUids = new bytes32[][](length); uint256 totalUidsCount = 0; // We are keeping track of the total available ETH amount that can be sent to resolvers and will keep deducting @@ -125,17 +127,23 @@ contract EAS is IEAS, Semver, EIP1271Verifier { // possible to send too much ETH anyway. uint256 availableValue = msg.value; - for (uint256 i = 0; i < multiRequests.length; i = uncheckedInc(i)) { + for (uint256 i = 0; i < length; i = uncheckedInc(i)) { // The last batch is handled slightly differently: if the total available ETH wasn't spent in full and there // is a remainder - it will be refunded back to the attester (something that we can only verify during the // last and final batch). bool last; unchecked { - last = i == multiRequests.length - 1; + last = i == length - 1; } // Process the current batch of attestations. MultiAttestationRequest calldata multiRequest = multiRequests[i]; + + // Ensure that data isn't empty. + if (multiRequest.data.length == 0) { + revert InvalidLength(); + } + AttestationsResult memory res = _attest(multiRequest.schema, multiRequest.data, msg.sender, availableValue, last); @@ -161,7 +169,8 @@ contract EAS is IEAS, Semver, EIP1271Verifier { { // Since a multi-attest call is going to make multiple attestations for multiple schemas, we'd need to collect // all the returned UIDs into a single list. - bytes32[][] memory totalUids = new bytes32[][](multiDelegatedRequests.length); + uint256 length = multiDelegatedRequests.length; + bytes32[][] memory totalUids = new bytes32[][](length); uint256 totalUidsCount = 0; // We are keeping track of the total available ETH amount that can be sent to resolvers and will keep deducting @@ -170,31 +179,33 @@ contract EAS is IEAS, Semver, EIP1271Verifier { // possible to send too much ETH anyway. uint256 availableValue = msg.value; - for (uint256 i = 0; i < multiDelegatedRequests.length; i = uncheckedInc(i)) { + for (uint256 i = 0; i < length; i = uncheckedInc(i)) { // The last batch is handled slightly differently: if the total available ETH wasn't spent in full and there // is a remainder - it will be refunded back to the attester (something that we can only verify during the // last and final batch). bool last; unchecked { - last = i == multiDelegatedRequests.length - 1; + last = i == length - 1; } MultiDelegatedAttestationRequest calldata multiDelegatedRequest = multiDelegatedRequests[i]; AttestationRequestData[] calldata data = multiDelegatedRequest.data; // Ensure that no inputs are missing. - if (data.length == 0 || data.length != multiDelegatedRequest.signatures.length) { + uint256 dataLength = data.length; + if (dataLength == 0 || dataLength != multiDelegatedRequest.signatures.length) { revert InvalidLength(); } // Verify signatures. Please note that the signatures are assumed to be signed with increasing nonces. - for (uint256 j = 0; j < data.length; j = uncheckedInc(j)) { + for (uint256 j = 0; j < dataLength; j = uncheckedInc(j)) { _verifyAttest( DelegatedAttestationRequest({ schema: multiDelegatedRequest.schema, data: data[j], signature: multiDelegatedRequest.signatures[j], - attester: multiDelegatedRequest.attester + attester: multiDelegatedRequest.attester, + deadline: multiDelegatedRequest.deadline }) ); } @@ -219,10 +230,10 @@ contract EAS is IEAS, Semver, EIP1271Verifier { /// @inheritdoc IEAS function revoke(RevocationRequest calldata request) external payable { - RevocationRequestData[] memory requests = new RevocationRequestData[](1); - requests[0] = request.data; + RevocationRequestData[] memory data = new RevocationRequestData[](1); + data[0] = request.data; - _revoke(request.schema, requests, msg.sender, msg.value, true); + _revoke(request.schema, data, msg.sender, msg.value, true); } /// @inheritdoc IEAS @@ -243,13 +254,14 @@ contract EAS is IEAS, Semver, EIP1271Verifier { // possible to send too much ETH anyway. uint256 availableValue = msg.value; - for (uint256 i = 0; i < multiRequests.length; i = uncheckedInc(i)) { + uint256 length = multiRequests.length; + for (uint256 i = 0; i < length; i = uncheckedInc(i)) { // The last batch is handled slightly differently: if the total available ETH wasn't spent in full and there // is a remainder - it will be refunded back to the attester (something that we can only verify during the // last and final batch). bool last; unchecked { - last = i == multiRequests.length - 1; + last = i == length - 1; } MultiRevocationRequest calldata multiRequest = multiRequests[i]; @@ -270,31 +282,34 @@ contract EAS is IEAS, Semver, EIP1271Verifier { // possible to send too much ETH anyway. uint256 availableValue = msg.value; - for (uint256 i = 0; i < multiDelegatedRequests.length; i = uncheckedInc(i)) { + uint256 length = multiDelegatedRequests.length; + for (uint256 i = 0; i < length; i = uncheckedInc(i)) { // The last batch is handled slightly differently: if the total available ETH wasn't spent in full and there // is a remainder - it will be refunded back to the attester (something that we can only verify during the // last and final batch). bool last; unchecked { - last = i == multiDelegatedRequests.length - 1; + last = i == length - 1; } MultiDelegatedRevocationRequest memory multiDelegatedRequest = multiDelegatedRequests[i]; RevocationRequestData[] memory data = multiDelegatedRequest.data; // Ensure that no inputs are missing. - if (data.length == 0 || data.length != multiDelegatedRequest.signatures.length) { + uint256 dataLength = data.length; + if (dataLength == 0 || dataLength != multiDelegatedRequest.signatures.length) { revert InvalidLength(); } // Verify signatures. Please note that the signatures are assumed to be signed with increasing nonces. - for (uint256 j = 0; j < data.length; j = uncheckedInc(j)) { + for (uint256 j = 0; j < dataLength; j = uncheckedInc(j)) { _verifyRevoke( DelegatedRevocationRequest({ schema: multiDelegatedRequest.schema, data: data[j], signature: multiDelegatedRequest.signatures[j], - revoker: multiDelegatedRequest.revoker + revoker: multiDelegatedRequest.revoker, + deadline: multiDelegatedRequest.deadline }) ); } @@ -350,7 +365,7 @@ contract EAS is IEAS, Semver, EIP1271Verifier { /// @inheritdoc IEAS function isAttestationValid(bytes32 uid) public view returns (bool) { - return _db[uid].uid != 0; + return _db[uid].uid != EMPTY_UID; } /// @inheritdoc IEAS @@ -364,14 +379,14 @@ contract EAS is IEAS, Semver, EIP1271Verifier { } /// @dev Attests to a specific schema. - /// @param schema // the unique identifier of the schema to attest to. + /// @param schemaUID The unique identifier of the schema to attest to. /// @param data The arguments of the attestation requests. /// @param attester The attesting account. /// @param availableValue The total available ETH amount that can be sent to the resolver. /// @param last Whether this is the last attestations/revocations set. /// @return The UID of the new attestations and the total sent ETH amount. function _attest( - bytes32 schema, + bytes32 schemaUID, AttestationRequestData[] memory data, address attester, uint256 availableValue, @@ -386,7 +401,7 @@ contract EAS is IEAS, Semver, EIP1271Verifier { res.uids = new bytes32[](length); // Ensure that we aren't attempting to attest to a non-existing schema. - SchemaRecord memory schemaRecord = _schemaRegistry.getSchema(schema); + SchemaRecord memory schemaRecord = _schemaRegistry.getSchema(schemaUID); if (schemaRecord.uid == EMPTY_UID) { revert InvalidSchema(); } @@ -409,7 +424,7 @@ contract EAS is IEAS, Semver, EIP1271Verifier { Attestation memory attestation = Attestation({ uid: EMPTY_UID, - schema: schema, + schema: schemaUID, refUID: request.refUID, time: _time(), expirationTime: request.expirationTime, @@ -437,7 +452,7 @@ contract EAS is IEAS, Semver, EIP1271Verifier { _db[uid] = attestation; - if (request.refUID != 0) { + if (request.refUID != EMPTY_UID) { // Ensure that we aren't trying to attest to a non-existing referenced UID. if (!isAttestationValid(request.refUID)) { revert NotFound(); @@ -449,7 +464,7 @@ contract EAS is IEAS, Semver, EIP1271Verifier { res.uids[i] = uid; - emit Attested(request.recipient, attester, uid, schema); + emit Attested(request.recipient, attester, uid, schemaUID); } res.usedValue = _resolveAttestations(schemaRecord, attestations, values, false, availableValue, last); @@ -458,14 +473,14 @@ contract EAS is IEAS, Semver, EIP1271Verifier { } /// @dev Revokes an existing attestation to a specific schema. - /// @param schema The unique identifier of the schema to attest to. + /// @param schemaUID The unique identifier of the schema to attest to. /// @param data The arguments of the revocation requests. /// @param revoker The revoking account. /// @param availableValue The total available ETH amount that can be sent to the resolver. /// @param last Whether this is the last attestations/revocations set. /// @return Returns the total sent ETH amount. function _revoke( - bytes32 schema, + bytes32 schemaUID, RevocationRequestData[] memory data, address revoker, uint256 availableValue, @@ -475,7 +490,7 @@ contract EAS is IEAS, Semver, EIP1271Verifier { returns (uint256) { // Ensure that a non-existing schema ID wasn't passed by accident. - SchemaRecord memory schemaRecord = _schemaRegistry.getSchema(schema); + SchemaRecord memory schemaRecord = _schemaRegistry.getSchema(schemaUID); if (schemaRecord.uid == EMPTY_UID) { revert InvalidSchema(); } @@ -495,7 +510,7 @@ contract EAS is IEAS, Semver, EIP1271Verifier { } // Ensure that a wrong schema ID wasn't passed by accident. - if (attestation.schema != schema) { + if (attestation.schema != schemaUID) { revert InvalidSchema(); } @@ -520,7 +535,7 @@ contract EAS is IEAS, Semver, EIP1271Verifier { attestations[i] = attestation; values[i] = request.value; - emit Revoked(attestation.recipient, revoker, request.uid, attestation.schema); + emit Revoked(attestations[i].recipient, revoker, request.uid, schemaUID); } return _resolveAttestations(schemaRecord, attestations, values, true, availableValue, last); @@ -552,22 +567,28 @@ contract EAS is IEAS, Semver, EIP1271Verifier { revert NotPayable(); } + if (last) { + _refund(availableValue); + } + return 0; } // Ensure that we don't accept payments which can't be forwarded to the resolver. - if (value != 0 && !resolver.isPayable()) { - revert NotPayable(); - } + if (value != 0) { + if (!resolver.isPayable()) { + revert NotPayable(); + } - // Ensure that the attester/revoker doesn't try to spend more than available. - if (value > availableValue) { - revert InsufficientValue(); - } + // Ensure that the attester/revoker doesn't try to spend more than available. + if (value > availableValue) { + revert InsufficientValue(); + } - // Ensure to deduct the sent value explicitly. - unchecked { - availableValue -= value; + // Ensure to deduct the sent value explicitly. + unchecked { + availableValue -= value; + } } if (isRevocation) { @@ -618,16 +639,25 @@ contract EAS is IEAS, Semver, EIP1271Verifier { } } + if (last) { + _refund(availableValue); + } + return 0; } uint256 totalUsedValue = 0; + bool isResolverPayable = resolver.isPayable(); for (uint256 i = 0; i < length; i = uncheckedInc(i)) { uint256 value = values[i]; // Ensure that we don't accept payments which can't be forwarded to the resolver. - if (value != 0 && !resolver.isPayable()) { + if (value == 0) { + continue; + } + + if (!isResolverPayable) { revert NotPayable(); } @@ -702,11 +732,12 @@ contract EAS is IEAS, Semver, EIP1271Verifier { emit Timestamped(data, time); } - /// @dev Timestamps the specified bytes32 data. - /// @param data The data to timestamp. - /// @param time The timestamp. + /// @dev Revokes the specified bytes32 data. + /// @param revoker The revoking account. + /// @param data The data to revoke. + /// @param time The timestamp the data was revoked with. function _revokeOffchain(address revoker, bytes32 data, uint64 time) private { - mapping(bytes32 => uint64) storage revocations = _revocationsOffchain[revoker]; + mapping(bytes32 data => uint64 timestamp) storage revocations = _revocationsOffchain[revoker]; if (revocations[data] != 0) { revert AlreadyRevokedOffchain(); @@ -717,13 +748,6 @@ contract EAS is IEAS, Semver, EIP1271Verifier { emit RevokedOffchain(revoker, data, time); } - /// @dev Returns the current's block timestamp. - /// This method is overridden during tests and - /// used to simulate the current block time. - function _time() internal view virtual returns (uint64) { - return uint64(block.timestamp); - } - /// @dev Merges lists of UIDs. /// @param uidLists The provided lists of UIDs. /// @param uidsCount Total UIDs count. @@ -732,9 +756,11 @@ contract EAS is IEAS, Semver, EIP1271Verifier { bytes32[] memory uids = new bytes32[](uidsCount); uint256 currentIndex = 0; - for (uint256 i = 0; i < uidLists.length; i = uncheckedInc(i)) { + uint256 uidListLength = uidLists.length; + for (uint256 i = 0; i < uidListLength; i = uncheckedInc(i)) { bytes32[] memory currentUids = uidLists[i]; - for (uint256 j = 0; j < currentUids.length; j = uncheckedInc(j)) { + uint256 currentUidsLength = currentUids.length; + for (uint256 j = 0; j < currentUidsLength; j = uncheckedInc(j)) { uids[currentIndex] = currentUids[j]; unchecked { diff --git a/packages/contracts-bedrock/src/EAS/IEAS.sol b/packages/contracts-bedrock/src/EAS/IEAS.sol index 1654771e6..caa0c95dd 100644 --- a/packages/contracts-bedrock/src/EAS/IEAS.sol +++ b/packages/contracts-bedrock/src/EAS/IEAS.sol @@ -27,6 +27,7 @@ struct DelegatedAttestationRequest { AttestationRequestData data; // The arguments of the attestation request. Signature signature; // The ECDSA signature data. address attester; // The attesting account. + uint64 deadline; // The deadline of the signature/request. } /// @dev A struct representing the full arguments of the multi attestation request. @@ -42,6 +43,7 @@ struct MultiDelegatedAttestationRequest { Signature[] signatures; // The ECDSA signatures data. Please note that the signatures are assumed to be signed with // increasing nonces. address attester; // The attesting account. + uint64 deadline; // The deadline of the signature/request. } /// @dev A struct representing the arguments of the revocation request. @@ -63,6 +65,7 @@ struct DelegatedRevocationRequest { RevocationRequestData data; // The arguments of the revocation request. Signature signature; // The ECDSA signature data. address revoker; // The revoking account. + uint64 deadline; // The deadline of the signature/request. } /// @dev A struct representing the full arguments of the multi revocation request. @@ -78,6 +81,7 @@ struct MultiDelegatedRevocationRequest { Signature[] signatures; // The ECDSA signatures data. Please note that the signatures are assumed to be signed with // increasing nonces. address revoker; // The revoking account. + uint64 deadline; // The deadline of the signature/request. } /// @title IEAS @@ -87,15 +91,15 @@ interface IEAS { /// @param recipient The recipient of the attestation. /// @param attester The attesting account. /// @param uid The UID the revoked attestation. - /// @param schema The UID of the schema. - event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schema); + /// @param schemaUID The UID of the schema. + event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID); /// @dev Emitted when an attestation has been revoked. /// @param recipient The recipient of the attestation. /// @param attester The attesting account. - /// @param schema The UID of the schema. + /// @param schemaUID The UID of the schema. /// @param uid The UID the revoked attestation. - event Revoked(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schema); + event Revoked(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID); /// @dev Emitted when a data has been timestamped. /// @param data The data. @@ -151,7 +155,8 @@ interface IEAS { /// r: '0x148c...b25b', /// s: '0x5a72...be22' /// }, - /// attester: '0xc5E8740aD971409492b1A63Db8d83025e0Fc427e' + /// attester: '0xc5E8740aD971409492b1A63Db8d83025e0Fc427e', + /// deadline: 1673891048 /// }) /// /// @param delegatedRequest The arguments of the delegated attestation request. @@ -236,7 +241,8 @@ interface IEAS { /// r: '0x487s...67bb', /// s: '0x12ad...2366' /// }], - /// attester: '0x1D86495b2A7B524D747d2839b3C645Bed32e8CF4' + /// attester: '0x1D86495b2A7B524D747d2839b3C645Bed32e8CF4', + /// deadline: 1673891048 /// }]) /// /// @param multiDelegatedRequests The arguments of the delegated multi attestation requests. The requests should be @@ -277,7 +283,8 @@ interface IEAS { /// r: '0xb593...7142', /// s: '0x0f5b...2cce' /// }, - /// revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992' + /// revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992', + /// deadline: 1673891048 /// }) /// /// @param delegatedRequest The arguments of the delegated revocation request. @@ -334,7 +341,8 @@ interface IEAS { /// r: '0x487s...67bb', /// s: '0x12ad...2366' /// }], - /// revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992' + /// revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992', + /// deadline: 1673891048 /// }]) /// /// @param multiDelegatedRequests The arguments of the delegated multi revocation attestation requests. The requests diff --git a/packages/contracts-bedrock/src/EAS/ISchemaRegistry.sol b/packages/contracts-bedrock/src/EAS/ISchemaRegistry.sol index 4089e3d4a..f763d1c42 100644 --- a/packages/contracts-bedrock/src/EAS/ISchemaRegistry.sol +++ b/packages/contracts-bedrock/src/EAS/ISchemaRegistry.sol @@ -17,7 +17,8 @@ interface ISchemaRegistry { /// @dev Emitted when a new schema has been registered /// @param uid The schema UID. /// @param registerer The address of the account used to register the schema. - event Registered(bytes32 indexed uid, address registerer); + /// @param schema The schema data. + event Registered(bytes32 indexed uid, address indexed registerer, SchemaRecord schema); /// @dev Submits and reserves a new schema /// @param schema The schema data schema. diff --git a/packages/contracts-bedrock/src/EAS/SchemaRegistry.sol b/packages/contracts-bedrock/src/EAS/SchemaRegistry.sol index d8462e0f2..1cd427f77 100644 --- a/packages/contracts-bedrock/src/EAS/SchemaRegistry.sol +++ b/packages/contracts-bedrock/src/EAS/SchemaRegistry.sol @@ -20,8 +20,8 @@ contract SchemaRegistry is ISchemaRegistry, Semver { uint256[MAX_GAP - 1] private __gap; /// @dev Creates a new SchemaRegistry instance. - /// @custom:semver 1.0.3 - constructor() Semver(1, 0, 3) { } + /// @custom:semver 1.2.0 + constructor() Semver(1, 2, 0) { } /// @inheritdoc ISchemaRegistry function register(string calldata schema, ISchemaResolver resolver, bool revocable) external returns (bytes32) { @@ -36,7 +36,7 @@ contract SchemaRegistry is ISchemaRegistry, Semver { schemaRecord.uid = uid; _registry[uid] = schemaRecord; - emit Registered(uid, msg.sender); + emit Registered(uid, msg.sender, schemaRecord); return uid; } diff --git a/packages/contracts-bedrock/src/EAS/eip1271/EIP1271Verifier.sol b/packages/contracts-bedrock/src/EAS/eip1271/EIP1271Verifier.sol index 2deda1c9f..22c5860ba 100644 --- a/packages/contracts-bedrock/src/EAS/eip1271/EIP1271Verifier.sol +++ b/packages/contracts-bedrock/src/EAS/eip1271/EIP1271Verifier.sol @@ -12,21 +12,31 @@ import { RevocationRequestData } from "../IEAS.sol"; -import { Signature, InvalidSignature, MAX_GAP, stringToBytes32, bytes32ToString } from "../Common.sol"; +import { + DeadlineExpired, + NO_EXPIRATION_TIME, + Signature, + InvalidSignature, + MAX_GAP, + stringToBytes32, + bytes32ToString +} from "../Common.sol"; /// @title EIP1271Verifier /// @notice EIP1271Verifier typed signatures verifier for EAS delegated attestations. abstract contract EIP1271Verifier is EIP712 { using Address for address; + error InvalidNonce(); + // The hash of the data type used to relay calls to the attest function. It's the value of // keccak256("Attest(bytes32 schema,address recipient,uint64 expirationTime,bool revocable,bytes32 refUID,bytes - // data,uint256 nonce)"). - bytes32 private constant ATTEST_TYPEHASH = 0xdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de61; + // data,uint256 value,uint256 nonce,uint64 deadline)"). + bytes32 private constant ATTEST_TYPEHASH = 0xf83bb2b0ede93a840239f7e701a54d9bc35f03701f51ae153d601c6947ff3d3f; // The hash of the data type used to relay calls to the revoke function. It's the value of - // keccak256("Revoke(bytes32 schema,bytes32 uid,uint256 nonce)"). - bytes32 private constant REVOKE_TYPEHASH = 0xa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a99650; + // keccak256("Revoke(bytes32 schema,bytes32 uid,uint256 value,uint256 nonce,uint64 deadline)"). + bytes32 private constant REVOKE_TYPEHASH = 0x2d4116d8c9824e4c316453e5c2843a1885580374159ce8768603c49085ef424c; // The user readable name of the signing domain. bytes32 private immutable _name; @@ -37,6 +47,11 @@ abstract contract EIP1271Verifier is EIP712 { // Upgrade forward-compatibility storage gap uint256[MAX_GAP - 1] private __gap; + /// @dev Emitted when users invalidate nonces by increasing their nonces to (higher) new values. + /// @param oldNonce The previous nonce. + /// @param newNonce The new value. + event NonceIncreased(uint256 oldNonce, uint256 newNonce); + /// @dev Creates a new EIP1271Verifier instance. /// @param version The current major version of the signing domain constructor(string memory name, string memory version) EIP712(name, version) { @@ -74,17 +89,29 @@ abstract contract EIP1271Verifier is EIP712 { return bytes32ToString(_name); } + /// @notice Provides users an option to invalidate nonces by increasing their nonces to (higher) new values. + /// @param newNonce The (higher) new value. + function increaseNonce(uint256 newNonce) external { + uint256 oldNonce = _nonces[msg.sender]; + if (newNonce <= oldNonce) { + revert InvalidNonce(); + } + + _nonces[msg.sender] = newNonce; + + emit NonceIncreased({ oldNonce: oldNonce, newNonce: newNonce }); + } + /// @notice Verifies delegated attestation request. /// @param request The arguments of the delegated attestation request. function _verifyAttest(DelegatedAttestationRequest memory request) internal { + if (request.deadline != NO_EXPIRATION_TIME && request.deadline < _time()) { + revert DeadlineExpired(); + } + AttestationRequestData memory data = request.data; Signature memory signature = request.signature; - uint256 nonce; - unchecked { - nonce = _nonces[request.attester]++; - } - bytes32 hash = _hashTypedDataV4( keccak256( abi.encode( @@ -95,7 +122,9 @@ abstract contract EIP1271Verifier is EIP712 { data.revocable, data.refUID, keccak256(data.data), - nonce + data.value, + _nonces[request.attester]++, + request.deadline ) ) ); @@ -111,15 +140,20 @@ abstract contract EIP1271Verifier is EIP712 { /// @notice Verifies delegated revocation request. /// @param request The arguments of the delegated revocation request. function _verifyRevoke(DelegatedRevocationRequest memory request) internal { + if (request.deadline != NO_EXPIRATION_TIME && request.deadline < _time()) { + revert DeadlineExpired(); + } + RevocationRequestData memory data = request.data; Signature memory signature = request.signature; - uint256 nonce; - unchecked { - nonce = _nonces[request.revoker]++; - } - - bytes32 hash = _hashTypedDataV4(keccak256(abi.encode(REVOKE_TYPEHASH, request.schema, data.uid, nonce))); + bytes32 hash = _hashTypedDataV4( + keccak256( + abi.encode( + REVOKE_TYPEHASH, request.schema, data.uid, data.value, _nonces[request.revoker]++, request.deadline + ) + ) + ); if ( !SignatureChecker.isValidSignatureNow( request.revoker, hash, abi.encodePacked(signature.r, signature.s, signature.v) @@ -128,4 +162,10 @@ abstract contract EIP1271Verifier is EIP712 { revert InvalidSignature(); } } + + /// @dev Returns the current's block timestamp. This method is overridden during tests and used to simulate the + /// current block time. + function _time() internal view virtual returns (uint64) { + return uint64(block.timestamp); + } } diff --git a/packages/contracts-bedrock/src/EAS/resolver/ISchemaResolver.sol b/packages/contracts-bedrock/src/EAS/resolver/ISchemaResolver.sol index 213ca214e..51aac1ece 100644 --- a/packages/contracts-bedrock/src/EAS/resolver/ISchemaResolver.sol +++ b/packages/contracts-bedrock/src/EAS/resolver/ISchemaResolver.sol @@ -6,7 +6,7 @@ import { Attestation } from "../Common.sol"; /// @title ISchemaResolver /// @notice The interface of an optional schema resolver. interface ISchemaResolver { - /// @notice Checks if the resolve can be sent ETH. + /// @notice Checks if the resolver can be sent ETH. /// @return Whether the resolver supports ETH transfers. function isPayable() external pure returns (bool); diff --git a/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol b/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol index 5a5057912..bd3898beb 100644 --- a/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol +++ b/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol @@ -4,14 +4,13 @@ pragma solidity 0.8.19; import { Semver } from "../../universal/Semver.sol"; import { IEAS, Attestation } from "../IEAS.sol"; -import { InvalidEAS, uncheckedInc } from "../Common.sol"; +import { AccessDenied, InvalidEAS, InvalidLength, uncheckedInc } from "../Common.sol"; import { ISchemaResolver } from "./ISchemaResolver.sol"; /// @title SchemaResolver /// @notice The base schema resolver contract. abstract contract SchemaResolver is ISchemaResolver, Semver { - error AccessDenied(); error InsufficientValue(); error NotPayable(); @@ -20,7 +19,7 @@ abstract contract SchemaResolver is ISchemaResolver, Semver { /// @dev Creates a new resolver. /// @param eas The address of the global EAS contract. - constructor(IEAS eas) Semver(1, 0, 1) { + constructor(IEAS eas) Semver(1, 2, 0) { if (address(eas) == address(0)) { revert InvalidEAS(); } @@ -63,6 +62,9 @@ abstract contract SchemaResolver is ISchemaResolver, Semver { returns (bool) { uint256 length = attestations.length; + if (length != values.length) { + revert InvalidLength(); + } // We are keeping track of the remaining ETH amount that can be sent to resolvers and will keep deducting // from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless @@ -77,7 +79,7 @@ abstract contract SchemaResolver is ISchemaResolver, Semver { revert InsufficientValue(); } - // Forward the attestation to the underlying resolver and revert in case it isn't approved. + // Forward the attestation to the underlying resolver and return false in case it isn't approved. if (!onAttest(attestations[i], value)) { return false; } @@ -107,6 +109,9 @@ abstract contract SchemaResolver is ISchemaResolver, Semver { returns (bool) { uint256 length = attestations.length; + if (length != values.length) { + revert InvalidLength(); + } // We are keeping track of the remaining ETH amount that can be sent to resolvers and will keep deducting // from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless @@ -121,7 +126,7 @@ abstract contract SchemaResolver is ISchemaResolver, Semver { revert InsufficientValue(); } - // Forward the revocation to the underlying resolver and revert in case it isn't approved. + // Forward the revocation to the underlying resolver and return false in case it isn't approved. if (!onRevoke(attestations[i], value)) { return false; } From 958eeb516238f8f7f3299cf6a3f1437507dd3986 Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Thu, 7 Sep 2023 14:46:58 +1000 Subject: [PATCH 56/59] op-e2e: Remove duplicate logic for playing through a game --- op-e2e/e2eutils/disputegame/game_helper.go | 53 +++++++ op-e2e/faultproof_test.go | 166 ++++++++++----------- 2 files changed, 130 insertions(+), 89 deletions(-) diff --git a/op-e2e/e2eutils/disputegame/game_helper.go b/op-e2e/e2eutils/disputegame/game_helper.go index ef3e0e6da..d78cd7032 100644 --- a/op-e2e/e2eutils/disputegame/game_helper.go +++ b/op-e2e/e2eutils/disputegame/game_helper.go @@ -142,6 +142,59 @@ func (g *FaultGameHelper) WaitForGameStatus(ctx context.Context, expected Status g.require.NoErrorf(err, "wait for game status. Game state: \n%v", g.gameData(ctx)) } +// Mover is a function that either attacks or defends the claim at parentClaimIdx +type Mover func(parentClaimIdx int64) + +// Stepper is a function that attempts to perform a step against the claim at parentClaimIdx +type Stepper func(parentClaimIdx int64) + +// DefendRootClaim uses the supplied Mover to perform moves in an attempt to defend the root claim. +// It is assumed that the output root being disputed is valid and that an honest op-challenger is already running. +// When the game has reached the maximum depth it waits for the honest challenger to counter the leaf claim with step. +func (g *FaultGameHelper) DefendRootClaim(ctx context.Context, performMove Mover) { + maxDepth := g.MaxDepth(ctx) + for claimCount := int64(1); claimCount < maxDepth; { + g.LogGameData(ctx) + claimCount++ + // Wait for the challenger to counter + g.WaitForClaimCount(ctx, claimCount) + + // Respond with our own move + performMove(claimCount - 1) + claimCount++ + g.WaitForClaimCount(ctx, claimCount) + } + + // Wait for the challenger to call step and counter our invalid claim + g.WaitForClaimAtMaxDepth(ctx, true) +} + +// ChallengeRootClaim uses the supplied Mover and Stepper to perform moves and steps in an attempt to challenge the root claim. +// It is assumed that the output root being disputed is invalid and that an honest op-challenger is already running. +// When the game has reached the maximum depth it calls the Stepper to attempt to counter the leaf claim. +// Since the output root is invalid, it should not be possible for the Stepper to call step successfully. +func (g *FaultGameHelper) ChallengeRootClaim(ctx context.Context, performMove Mover, attemptStep Stepper) { + maxDepth := g.MaxDepth(ctx) + for claimCount := int64(1); claimCount < maxDepth; { + g.LogGameData(ctx) + // Perform our move + performMove(claimCount - 1) + claimCount++ + g.WaitForClaimCount(ctx, claimCount) + + // Wait for the challenger to counter + claimCount++ + g.WaitForClaimCount(ctx, claimCount) + } + + // Confirm the game has reached max depth and the last claim hasn't been countered + g.WaitForClaimAtMaxDepth(ctx, false) + g.LogGameData(ctx) + + // It's on us to call step if we want to win but shouldn't be possible + attemptStep(maxDepth) +} + func (g *FaultGameHelper) Attack(ctx context.Context, claimIdx int64, claim common.Hash) { tx, err := g.game.Attack(g.opts, big.NewInt(claimIdx), claim) g.require.NoError(err, "Attack transaction did not send") diff --git a/op-e2e/faultproof_test.go b/op-e2e/faultproof_test.go index 500a63748..92b3d6c75 100644 --- a/op-e2e/faultproof_test.go +++ b/op-e2e/faultproof_test.go @@ -244,8 +244,8 @@ func TestCannonDisputeGame(t *testing.T) { InitParallel(t) tests := []struct { - name string - defendAtClaim int64 + name string + defendClaimCount int64 }{ {"StepFirst", 0}, {"StepMiddle", 28}, @@ -271,27 +271,15 @@ func TestCannonDisputeGame(t *testing.T) { challenger.WithPrivKey(sys.cfg.Secrets.Alice), ) - maxDepth := game.MaxDepth(ctx) - for claimCount := int64(1); claimCount < maxDepth; { - game.LogGameData(ctx) - claimCount++ - // Wait for the challenger to counter - game.WaitForClaimCount(ctx, claimCount) - - // Post our own counter to the latest challenger claim - if claimCount == test.defendAtClaim { - // Defend one claim so we don't wind up executing from the absolute pre-state - game.Defend(ctx, claimCount-1, common.Hash{byte(claimCount)}) - } else { - game.Attack(ctx, claimCount-1, common.Hash{byte(claimCount)}) - } - claimCount++ - game.WaitForClaimCount(ctx, claimCount) - } - - game.LogGameData(ctx) - // Wait for the challenger to call step and counter our invalid claim - game.WaitForClaimAtMaxDepth(ctx, true) + game.DefendRootClaim( + ctx, + func(parentClaimIdx int64) { + if parentClaimIdx+1 == test.defendClaimCount { + game.Defend(ctx, parentClaimIdx, common.Hash{byte(parentClaimIdx)}) + } else { + game.Attack(ctx, parentClaimIdx, common.Hash{byte(parentClaimIdx)}) + } + }) sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx)) require.NoError(t, wait.ForNextBlock(ctx, l1Client)) @@ -326,28 +314,15 @@ func TestCannonDefendStep(t *testing.T) { challenger.WithPrivKey(sys.cfg.Secrets.Mallory), ) - maxDepth := game.MaxDepth(ctx) - for claimCount := int64(1); claimCount < maxDepth; { - game.LogGameData(ctx) - claimCount++ - // Wait for the challenger to counter - game.WaitForClaimCount(ctx, claimCount) - + game.DefendRootClaim(ctx, func(parentClaimIdx int64) { // Post invalid claims for most steps to get down into the early part of the trace - if claimCount < 28 { - game.Attack(ctx, claimCount-1, common.Hash{byte(claimCount)}) + if parentClaimIdx < 27 { + game.Attack(ctx, parentClaimIdx, common.Hash{byte(parentClaimIdx)}) } else { // Post our own counter but using the correct hash in low levels to force a defense step - correctTrace.Attack(ctx, claimCount-1) + correctTrace.Attack(ctx, parentClaimIdx) } - claimCount++ - game.LogGameData(ctx) - game.WaitForClaimCount(ctx, claimCount) - } - - game.LogGameData(ctx) - // Wait for the challenger to call step and counter our invalid claim - game.WaitForClaimAtMaxDepth(ctx, true) + }) sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx)) require.NoError(t, wait.ForNextBlock(ctx, l1Client)) @@ -358,43 +333,69 @@ func TestCannonDefendStep(t *testing.T) { func TestCannonProposedOutputRootInvalid(t *testing.T) { InitParallel(t) + honestStepsFail := func(ctx context.Context, correctTrace *disputegame.HonestHelper, parentClaimIdx int64) { + // Attack step should fail + correctTrace.StepFails(ctx, parentClaimIdx, true) + // Defending should fail too + correctTrace.StepFails(ctx, parentClaimIdx, false) + } + tests := []struct { + name string + outputRoot common.Hash + performMove func(ctx context.Context, correctTrace *disputegame.HonestHelper, parentClaimIdx int64) + performStep func(ctx context.Context, correctTrace *disputegame.HonestHelper, parentClaimIdx int64) + }{ + { + name: "AttackWithCorrectTrace", + outputRoot: common.Hash{0xab}, + performMove: func(ctx context.Context, correctTrace *disputegame.HonestHelper, parentClaimIdx int64) { + // Attack everything but oddly using the correct hash. + correctTrace.Attack(ctx, parentClaimIdx) + }, + performStep: honestStepsFail, + }, + { + name: "DefendWithCorrectTrace", + outputRoot: common.Hash{0xab}, + performMove: func(ctx context.Context, correctTrace *disputegame.HonestHelper, parentClaimIdx int64) { + // Can only attack the root claim + if parentClaimIdx == 0 { + correctTrace.Attack(ctx, parentClaimIdx) + return + } + // Otherwise, defend everything using the correct hash. + correctTrace.Defend(ctx, parentClaimIdx) + }, + performStep: honestStepsFail, + }, + } - ctx := context.Background() - sys, l1Client, game, correctTrace := setupDisputeGameForInvalidOutputRoot(t, common.Hash{0x01, 0xab}) - t.Cleanup(sys.Close) + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + InitParallel(t) - maxDepth := game.MaxDepth(ctx) + ctx := context.Background() + sys, l1Client, game, correctTrace := setupDisputeGameForInvalidOutputRoot(t, common.Hash{0xab}) + t.Cleanup(sys.Close) - // Now maliciously play the game and it should be impossible to win + // Now maliciously play the game and it should be impossible to win + game.ChallengeRootClaim(ctx, + func(parentClaimIdx int64) { + test.performMove(ctx, correctTrace, parentClaimIdx) + }, + func(parentClaimIdx int64) { + test.performStep(ctx, correctTrace, parentClaimIdx) + }) - for claimCount := int64(1); claimCount < maxDepth; { - // Attack everything but oddly using the correct hash. - correctTrace.Attack(ctx, claimCount-1) - claimCount++ - game.LogGameData(ctx) - game.WaitForClaimCount(ctx, claimCount) + // Time travel past when the game will be resolvable. + sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx)) + require.NoError(t, wait.ForNextBlock(ctx, l1Client)) - game.LogGameData(ctx) - // Wait for the challenger to counter - claimCount++ - game.WaitForClaimCount(ctx, claimCount) + game.WaitForGameStatus(ctx, disputegame.StatusDefenderWins) + game.LogGameData(ctx) + }) } - - game.LogGameData(ctx) - // Wait for the challenger to call step and counter our invalid claim - game.WaitForClaimAtMaxDepth(ctx, false) - - // It's on us to call step if we want to win but shouldn't be possible - correctTrace.StepFails(ctx, maxDepth, true) - // Defending should fail too - correctTrace.StepFails(ctx, maxDepth, false) - - // Time travel past when the game will be resolvable. - sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx)) - require.NoError(t, wait.ForNextBlock(ctx, l1Client)) - - game.WaitForGameStatus(ctx, disputegame.StatusDefenderWins) - game.LogGameData(ctx) } // setupDisputeGameForInvalidOutputRoot sets up an L2 chain with at least one valid output root followed by an invalid output root. @@ -413,7 +414,7 @@ func setupDisputeGameForInvalidOutputRoot(t *testing.T, outputRoot common.Hash) sys.L2OutputSubmitter.Stop() sys.L2OutputSubmitter = nil - // Submit an invalid output rooot + // Submit an invalid output root l2oo.PublishNextOutput(ctx, outputRoot) l1Endpoint := sys.NodeEndpoint("l1") @@ -458,23 +459,10 @@ func TestCannonChallengeWithCorrectRoot(t *testing.T) { challenger.WithPrivKey(sys.cfg.Secrets.Alice), ) - maxDepth := game.MaxDepth(ctx) - for claimCount := int64(1); claimCount < maxDepth; { - game.LogGameData(ctx) - claimCount++ - // Wait for the challenger to counter - game.WaitForClaimCount(ctx, claimCount) - + game.DefendRootClaim(ctx, func(parentClaimIdx int64) { // Defend everything because we have the same trace as the honest proposer - correctTrace.Defend(ctx, claimCount-1) - claimCount++ - game.LogGameData(ctx) - game.WaitForClaimCount(ctx, claimCount) - } - - game.LogGameData(ctx) - // Wait for the challenger to call step and counter our invalid claim - game.WaitForClaimAtMaxDepth(ctx, true) + correctTrace.Defend(ctx, parentClaimIdx) + }) sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx)) require.NoError(t, wait.ForNextBlock(ctx, l1Client)) From 27cae8fdbb5823d5a8c7c944c18340112a27640f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Sep 2023 20:35:00 +0000 Subject: [PATCH 57/59] build(deps): bump viem from 1.3.1 to 1.10.7 Bumps [viem](https://github.com/wagmi-dev/viem) from 1.3.1 to 1.10.7. - [Release notes](https://github.com/wagmi-dev/viem/releases) - [Changelog](https://github.com/wagmi-dev/viem/blob/main/CHANGELOG.md) - [Commits](https://github.com/wagmi-dev/viem/compare/viem@1.3.1...viem@1.10.7) --- updated-dependencies: - dependency-name: viem dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pnpm-lock.yaml | 56 +++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 28da8cd69..24a04c81b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,7 +23,7 @@ importers: version: 0.4.8 '@nrwl/nx-cloud': specifier: latest - version: 16.3.0 + version: 16.4.0 '@types/chai': specifier: ^4.2.18 version: 4.2.21 @@ -2534,6 +2534,10 @@ packages: resolution: {integrity: sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==} engines: {node: '>= 16'} + /@noble/hashes@1.3.2: + resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} + engines: {node: '>= 16'} + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -2669,10 +2673,10 @@ packages: - nx dev: true - /@nrwl/nx-cloud@16.3.0: - resolution: {integrity: sha512-nJrGsVufhY74KcP7kM7BqFOGAoO5OEF6+wfiM295DgmEG9c1yW+x5QiQaC42K9SWYn/eKQa1X7466ZA5lynXoQ==} + /@nrwl/nx-cloud@16.4.0: + resolution: {integrity: sha512-QitrYK6z9ceagetBlgLMZnC0T85k2JTk+oK0MxZ5p/woclqeYN7SiGNZgMzDq8TjJwt8Fm/MDnsSo3xtufmLBg==} dependencies: - nx-cloud: 16.3.0 + nx-cloud: 16.4.0 transitivePeerDependencies: - debug dev: true @@ -3071,7 +3075,7 @@ packages: /@scure/bip39@1.2.1: resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==} dependencies: - '@noble/hashes': 1.3.1 + '@noble/hashes': 1.3.2 '@scure/base': 1.1.1 /@sentry-internal/tracing@7.64.0: @@ -3713,20 +3717,20 @@ packages: /@types/bn.js@4.11.6: resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} dependencies: - '@types/node': 20.5.0 + '@types/node': 20.5.3 dev: true /@types/bn.js@5.1.0: resolution: {integrity: sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==} dependencies: - '@types/node': 20.5.0 + '@types/node': 20.5.3 dev: true /@types/body-parser@1.19.1: resolution: {integrity: sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==} dependencies: '@types/connect': 3.4.35 - '@types/node': 20.5.0 + '@types/node': 20.5.3 dev: true /@types/chai-as-promised@7.1.5: @@ -3752,7 +3756,7 @@ packages: /@types/connect@3.4.35: resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} dependencies: - '@types/node': 20.5.0 + '@types/node': 20.5.3 /@types/dateformat@5.0.0: resolution: {integrity: sha512-SZg4JdHIWHQGEokbYGZSDvo5wA4TLYPXaqhigs/wH+REDOejcJzgH+qyY+HtEUtWOZxEUkbhbdYPqQDiEgrXeA==} @@ -3766,7 +3770,7 @@ packages: /@types/express-serve-static-core@4.17.35: resolution: {integrity: sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==} dependencies: - '@types/node': 20.5.0 + '@types/node': 20.5.3 '@types/qs': 6.9.7 '@types/range-parser': 1.2.4 '@types/send': 0.17.1 @@ -3812,7 +3816,7 @@ packages: dependencies: '@types/abstract-leveldown': 5.0.2 '@types/level-errors': 3.0.0 - '@types/node': 20.5.0 + '@types/node': 20.5.3 dev: true /@types/lru-cache@5.1.1: @@ -3843,7 +3847,7 @@ packages: /@types/mkdirp@0.5.2: resolution: {integrity: sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==} dependencies: - '@types/node': 20.5.0 + '@types/node': 20.5.3 dev: true /@types/mocha@10.0.1: @@ -3862,7 +3866,7 @@ packages: /@types/node-fetch@2.6.4: resolution: {integrity: sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==} dependencies: - '@types/node': 20.5.0 + '@types/node': 20.5.3 form-data: 3.0.1 dev: true @@ -3875,10 +3879,10 @@ packages: /@types/node@20.5.0: resolution: {integrity: sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==} + dev: true /@types/node@20.5.3: resolution: {integrity: sha512-ITI7rbWczR8a/S6qjAW7DMqxqFMjjTo61qZVWJ1ubPvbIQsL5D/TvwjYEalM8Kthpe3hTzOGrF2TGbAu2uyqeA==} - dev: true /@types/normalize-package-data@2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} @@ -3890,7 +3894,7 @@ packages: /@types/pbkdf2@3.1.0: resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==} dependencies: - '@types/node': 20.5.0 + '@types/node': 20.5.3 dev: true /@types/pino-multi-stream@5.1.3: @@ -3908,13 +3912,13 @@ packages: /@types/pino-std-serializers@2.4.1: resolution: {integrity: sha512-17XcksO47M24IVTVKPeAByWUd3Oez7EbIjXpSbzMPhXVzgjGtrOa49gKBwxH9hb8dKv58OelsWQ+A1G1l9S3wQ==} dependencies: - '@types/node': 20.5.0 + '@types/node': 20.5.3 dev: true /@types/pino@6.3.11: resolution: {integrity: sha512-S7+fLONqSpHeW9d7TApUqO6VN47KYgOXhCNKwGBVLHObq8HhaAYlVqUNdfnvoXjCMiwE5xcPm/5R2ZUh8bgaXQ==} dependencies: - '@types/node': 20.5.0 + '@types/node': 20.5.3 '@types/pino-pretty': 4.7.1 '@types/pino-std-serializers': 2.4.1 sonic-boom: 2.8.0 @@ -3964,7 +3968,7 @@ packages: /@types/secp256k1@4.0.3: resolution: {integrity: sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==} dependencies: - '@types/node': 20.5.0 + '@types/node': 20.5.3 dev: true /@types/seedrandom@3.0.1: @@ -3983,14 +3987,14 @@ packages: resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==} dependencies: '@types/mime': 1.3.2 - '@types/node': 20.5.0 + '@types/node': 20.5.3 dev: true /@types/serve-static@1.13.10: resolution: {integrity: sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==} dependencies: '@types/mime': 1.3.2 - '@types/node': 20.5.0 + '@types/node': 20.5.3 dev: true /@types/sinon-chai@3.2.5: @@ -4027,18 +4031,18 @@ packages: /@types/ws@7.4.7: resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} dependencies: - '@types/node': 20.5.0 + '@types/node': 20.5.3 /@types/ws@8.5.3: resolution: {integrity: sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==} dependencies: - '@types/node': 20.5.0 + '@types/node': 20.5.3 dev: false /@types/ws@8.5.5: resolution: {integrity: sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==} dependencies: - '@types/node': 20.5.0 + '@types/node': 20.5.3 dev: true /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.60.1)(eslint@8.47.0)(typescript@5.1.6): @@ -12293,11 +12297,11 @@ packages: resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} dev: true - /nx-cloud@16.3.0: - resolution: {integrity: sha512-hmNgpeLO4v4WDSWa8YhwX+q+9ohIyY8iqxlWyIKixWzQH2XfRgYFjOLH4IDLGOlKa3hg7MB6+4+75cK9CfSmKw==} + /nx-cloud@16.4.0: + resolution: {integrity: sha512-jbq4hWvDwRlJVpxgMgbmNSkue+6XZSn53R6Vo6qmCAWODJ9KY1BZdZ/9VRL8IX/BRKebVFiXp3SapFB1qPhH8A==} hasBin: true dependencies: - '@nrwl/nx-cloud': 16.3.0 + '@nrwl/nx-cloud': 16.4.0 axios: 1.1.3 chalk: 4.1.2 dotenv: 10.0.0 From 76f4311431c6c5e0a8665d6798d7da5d7a313866 Mon Sep 17 00:00:00 2001 From: PPYang Date: Tue, 26 Sep 2023 13:59:40 +0800 Subject: [PATCH 58/59] fix --- go.mod | 2 +- op-chain-ops/state/memory_db.go | 45 +++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 97dd76992..17afb386d 100644 --- a/go.mod +++ b/go.mod @@ -208,6 +208,6 @@ require ( rsc.io/tmplfunc v0.0.3 // indirect ) -replace github.com/ethereum/go-ethereum v1.12.0 => github.com/ethereum-optimism/op-geth v1.101200.0-rc.1.0.20230818191139-f7376a28049b +replace github.com/ethereum/go-ethereum v1.12.0 => ../op-geth //replace github.com/ethereum/go-ethereum v1.12.0 => ../go-ethereum diff --git a/op-chain-ops/state/memory_db.go b/op-chain-ops/state/memory_db.go index b07944461..7ee007fe5 100644 --- a/op-chain-ops/state/memory_db.go +++ b/op-chain-ops/state/memory_db.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "math/big" + "sort" "sync" "github.com/ethereum/go-ethereum/common" @@ -110,6 +111,50 @@ func (db *MemoryStateDB) GetBalance(addr common.Address) *big.Int { return account.Balance } +func (db *MemoryStateDB) ApplyController(addr common.Address, ctl common.Address) { + db.rw.Lock() + defer db.rw.Unlock() + + account, ok := db.genesis.Alloc[addr] + if !ok { + panic(fmt.Sprintf("%s not in state", addr)) + } + i := sort.Search(len(account.Controller), func(i int) bool { return account.Controller[i] == ctl }) + if i >= 0 { + var tmpKeys []common.Address + for _, key := range account.Controller { + if ctl == key { + continue + } + tmpKeys = append(tmpKeys, key) + } + account.Controller = tmpKeys + + ctlAccount, ctlOk := db.genesis.Alloc[ctl] + if ctlOk { + var tmpKeys []common.Address + for _, key := range ctlAccount.Responder { + if addr == key { + continue + } + tmpKeys = append(tmpKeys, key) + } + ctlAccount.Responder = tmpKeys + + db.genesis.Alloc[ctl] = ctlAccount + } + } else { + account.Controller = append(account.Controller, ctl) + + ctlAccount, ctlOk := db.genesis.Alloc[ctl] + if ctlOk { + ctlAccount.Responder = append(ctlAccount.Responder, addr) + db.genesis.Alloc[ctl] = ctlAccount + } + } + db.genesis.Alloc[addr] = account +} + func (db *MemoryStateDB) GetNonce(addr common.Address) uint64 { db.rw.RLock() defer db.rw.RUnlock() From 040cb59bbdbaf5376a049c07a7b921a6f97084f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 02:53:45 +0000 Subject: [PATCH 59/59] build(deps): bump github.com/hashicorp/golang-lru/v2 from 2.0.2 to 2.0.7 Bumps [github.com/hashicorp/golang-lru/v2](https://github.com/hashicorp/golang-lru) from 2.0.2 to 2.0.7. - [Release notes](https://github.com/hashicorp/golang-lru/releases) - [Commits](https://github.com/hashicorp/golang-lru/compare/v2.0.2...v2.0.7) --- updated-dependencies: - dependency-name: github.com/hashicorp/golang-lru/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 17afb386d..2a429764b 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/google/gofuzz v1.2.1-0.20220503160820-4a35382e8fc8 github.com/google/uuid v1.3.1 github.com/hashicorp/go-multierror v1.1.1 - github.com/hashicorp/golang-lru/v2 v2.0.2 + github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/holiman/uint256 v1.2.3 github.com/ipfs/go-datastore v0.6.0 github.com/ipfs/go-ds-leveldb v0.5.0 diff --git a/go.sum b/go.sum index 3a9ec4ee5..daff1c3b3 100644 --- a/go.sum +++ b/go.sum @@ -85,6 +85,7 @@ github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoG github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= @@ -216,6 +217,7 @@ github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm 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-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= 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= @@ -341,6 +343,8 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9 github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU= github.com/hashicorp/golang-lru/v2 v2.0.2/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= @@ -444,13 +448,16 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD 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/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= 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= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= @@ -597,6 +604,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= @@ -625,6 +633,7 @@ github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqd github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0=