diff --git a/.circleci/config.yml b/.circleci/config.yml index c193ef5d0..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 @@ -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 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 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/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") 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" 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..e5708c5f1 --- /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](./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/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..570f1fa97 --- /dev/null +++ b/docs/fault-proof-alpha/manual.md @@ -0,0 +1,111 @@ +## 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 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 records the parent of the block the transaction is included in. The `BlockOracle` emits +a log `Checkpoint(blockNumber, blockHash, childTimestamp)`. + +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: + +- `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. + +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 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. + +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 + +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: + +- `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 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 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 +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. + +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 new file mode 100644 index 000000000..c7ed6af0a --- /dev/null +++ b/docs/fault-proof-alpha/run-challenger.md @@ -0,0 +1,65 @@ +## 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 + +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 +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 +``` + + +### 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 ... +``` 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/go.mod b/go.mod index 97dd76992..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 @@ -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/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= 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/indexer/api/api.go b/indexer/api/api.go index 94cbade08..261ce1e14 100644 --- a/indexer/api/api.go +++ b/indexer/api/api.go @@ -4,42 +4,114 @@ 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 + log log.Logger + Router *chi.Mux + serverConfig config.ServerConfig + metricsConfig config.ServerConfig + metricsRegistry *prometheus.Registry } -func NewApi(logger log.Logger, bv database.BridgeTransfersView) *Api { - r := chi.NewRouter() - h := routes.NewRoutes(logger, bv, r) +const ( + MetricsNamespace = "op_indexer" +) + +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, 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(middleware.Recoverer) + 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, serverConfig: serverConfig, metricsConfig: metricsConfig} +} + +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() + }() - r.Use(middleware.Heartbeat("/healthz")) + errCh <- start(processCtx) + }() + } + + runProcess(a.startServer) + runProcess(a.startMetricsServer) + + wg.Wait() + + err := <-errCh + if err != nil { + a.log.Error("api stopped", "err", err) + } else { + a.log.Info("api stopped") + } - 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} + return err } -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} +func (a *Api) startServer(ctx context.Context) error { + 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) } 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..7b99bb8b8 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.ServerConfig{ + Host: "localhost", + Port: 8080, +} +var metricsConfig = config.ServerConfig{ + 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 ba8b69d62..e21b84b57 100644 --- a/indexer/cmd/indexer/cli.go +++ b/indexer/cmd/indexer/cli.go @@ -62,8 +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) + api := api.NewApi(log, db.BridgeTransfers, cfg.HTTPServer, cfg.MetricsServer) + return api.Start(ctx.Context) } func runAll(ctx *cli.Context) error { 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..0774fb529 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.Order("l2_block_headers.timestamp DESC").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/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" 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..7eb39f2a9 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" @@ -65,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} @@ -94,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 @@ -216,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, @@ -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..303d93631 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" ) @@ -65,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} @@ -94,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 @@ -165,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, @@ -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 - } - } -} diff --git a/indexer/ui/schema.prisma b/indexer/ui/schema.prisma index a48b3ce04..e3ba4a3c9 100644 --- a/indexer/ui/schema.prisma +++ b/indexer/ui/schema.prisma @@ -8,31 +8,30 @@ datasource db { } 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,14 +103,14 @@ 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 + parent_hash String @unique @db.VarChar + number Decimal @unique @db.Decimal timestamp Int 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) } 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-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 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/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() 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-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 4a336052a..c275ed69a 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 4308b3865..d55d4dae4 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" @@ -21,7 +22,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) } @@ -30,8 +31,7 @@ type GamePlayer struct { agreeWithProposedOutput bool loader GameInfo logger log.Logger - - completed bool + status gameTypes.GameStatus } func NewGamePlayer( @@ -56,14 +56,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 @@ -110,32 +110,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) @@ -144,11 +144,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 0a7d60d22..8c8e0bd4c 100644 --- a/op-challenger/game/fault/player_test.go +++ b/op-challenger/game/fault/player_test.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum-optimism/optimism/cannon/mipsevm" "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" @@ -23,8 +24,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") @@ -39,42 +40,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", @@ -86,9 +87,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")) @@ -97,19 +98,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) }) } } @@ -168,7 +169,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 @@ -180,7 +181,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 ff6983751..b7cc5815f 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..f90fca559 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,36 @@ 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) + c.m.RecordGameUpdateScheduled() + } + 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,15 +135,16 @@ 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() + c.m.RecordGameUpdateCompleted() return nil } 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 +153,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..41bf54b6e 100644 --- a/op-challenger/game/scheduler/scheduler.go +++ b/op-challenger/game/scheduler/scheduler.go @@ -11,6 +11,12 @@ import ( var ErrBusy = errors.New("busy scheduling previous update") +type SchedulerMetricer interface { + RecordGamesStatus(inProgress, defenderWon, challengerWon int) + RecordGameUpdateScheduled() + RecordGameUpdateCompleted() +} + type Scheduler struct { logger log.Logger coordinator *coordinator @@ -22,7 +28,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 +40,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..004ad1af1 100644 --- a/op-challenger/metrics/metrics.go +++ b/op-challenger/metrics/metrics.go @@ -24,6 +24,11 @@ type Metricer interface { RecordGameStep() RecordGameMove() RecordCannonExecutionTime(t float64) + + RecordGamesStatus(inProgress, defenderWon, challengerWon int) + + RecordGameUpdateScheduled() + RecordGameUpdateCompleted() } type Metrics struct { @@ -36,9 +41,13 @@ 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 + inflightGames prometheus.Gauge } var _ Metricer = (*Metrics)(nil) @@ -80,7 +89,21 @@ 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, + Name: "tracked_games", + Help: "Number of games being tracked by the challenger", + }, []string{ + "status", + }), + inflightGames: factory.NewGauge(prometheus.GaugeOpts{ + Namespace: Namespace, + Name: "inflight_games", + Help: "Number of games being tracked by the challenger", }), } } @@ -89,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) } @@ -120,3 +148,17 @@ 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)) +} + +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 2b4f9e982..d02bd594f 100644 --- a/op-challenger/metrics/noop.go +++ b/op-challenger/metrics/noop.go @@ -10,8 +10,15 @@ 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) {} + +func (*noopMetrics) RecordGameUpdateScheduled() {} +func (*noopMetrics) RecordGameUpdateCompleted() {} 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) 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/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/e2eutils/disputegame/game_helper.go b/op-e2e/e2eutils/disputegame/game_helper.go index ede4b1450..d78cd7032 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,60 @@ 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)) +} + +// 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) { @@ -156,6 +209,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/helper.go b/op-e2e/e2eutils/disputegame/helper.go index f13860fff..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" @@ -16,6 +17,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 +67,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 +83,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 +92,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 +150,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") @@ -179,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{ @@ -246,26 +245,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/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/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 50% rename from op-e2e/geth.go rename to op-e2e/e2eutils/geth/geth.go index 357f78e6f..ad02eac36 100644 --- a/op-e2e/geth.go +++ b/op-e2e/e2eutils/geth/geth.go @@ -1,26 +1,17 @@ -package op_e2e +package geth 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,101 +21,9 @@ 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) { +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{ @@ -137,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 } @@ -149,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, @@ -176,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, @@ -192,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) @@ -212,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/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/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/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 a3a07137e..92b3d6c75 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" @@ -243,8 +244,8 @@ func TestCannonDisputeGame(t *testing.T) { InitParallel(t) tests := []struct { - name string - defendAtClaim int64 + name string + defendClaimCount int64 }{ {"StepFirst", 0}, {"StepMiddle", 28}, @@ -270,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)) @@ -325,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)) @@ -355,8 +331,112 @@ func TestCannonDefendStep(t *testing.T) { game.LogGameData(ctx) } +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, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + InitParallel(t) + + 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 + game.ChallengeRootClaim(ctx, + func(parentClaimIdx int64) { + test.performMove(ctx, correctTrace, parentClaimIdx) + }, + func(parentClaimIdx int64) { + test.performStep(ctx, correctTrace, parentClaimIdx) + }) + + // 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 root + 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) ctx := context.Background() @@ -379,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)) diff --git a/op-e2e/l2_gossip_test.go b/op-e2e/l2_gossip_test.go new file mode 100644 index 000000000..530247401 --- /dev/null +++ b/op-e2e/l2_gossip_test.go @@ -0,0 +1,32 @@ +package op_e2e + +import ( + "testing" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestTxGossip(t *testing.T) { + InitParallel(t) + cfg := DefaultSystemConfig(t) + gethOpts := []geth.GethOption{ + geth.WithP2P(), + } + 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"] + 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) { + opts.ToAddr = &common.Address{0xaa} + opts.Value = common.Big1 + opts.VerifyOnClients(seqClient, verifClient) + }) +} 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 67af46ead..e88d12f9a 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" @@ -84,7 +85,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()) @@ -119,8 +120,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 +130,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{ @@ -138,7 +141,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, @@ -173,7 +176,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 @@ -424,7 +427,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 } @@ -441,7 +444,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 } @@ -457,7 +460,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, @@ -505,7 +508,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 9674df55a..b935bc88b 100644 --- a/op-e2e/system_test.go +++ b/op-e2e/system_test.go @@ -9,9 +9,9 @@ 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/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" @@ -30,6 +30,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" @@ -88,7 +89,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. @@ -260,14 +261,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 @@ -337,67 +338,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. @@ -431,7 +371,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 @@ -762,7 +702,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()) @@ -784,7 +724,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) @@ -914,9 +854,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) @@ -1313,7 +1253,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 @@ -1350,7 +1290,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 @@ -1372,7 +1312,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) @@ -1389,7 +1329,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()) @@ -1450,3 +1390,47 @@ 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 + _, err = wait.ForReceiptOK(context.Background(), l1, tx.Hash()) + require.NoError(t, err) + + // 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-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 5b17afe88..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" @@ -21,7 +22,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 +40,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 := 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(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 := geth.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) @@ -91,16 +94,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") + 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) - require.Nilf(t, err, "Waiting for L2 tx on verification client %d", i) + 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) } return receipt 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 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= 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-node/cmd/stateviz/main.go b/op-node/cmd/stateviz/main.go index 3e721eb63..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-node/http" "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/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/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/metrics/metrics.go b/op-node/metrics/metrics.go index ff232e739..c468ce6e5 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-node/http" "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" 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..91aad8121 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 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") + 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/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/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 } 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), 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-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)) +} 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 diff --git a/op-node/http/http.go b/op-service/httputil/http.go similarity index 96% rename from op-node/http/http.go rename to op-service/httputil/http.go index ff223ed29..8d15b9542 100644 --- a/op-node/http/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 bc307cfea..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 { @@ -14,15 +12,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) { 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 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 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; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 854ca3650..24a04c81b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,13 +17,13 @@ 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 '@nrwl/nx-cloud': specifier: latest - version: 16.3.0 + version: 16.4.0 '@types/chai': specifier: ^4.2.18 version: 4.2.21 @@ -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,31 +632,8 @@ 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.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 @@ -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: @@ -2693,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'} @@ -2828,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 @@ -3230,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: @@ -3872,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: @@ -3911,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==} @@ -3925,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 @@ -3971,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: @@ -4002,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: @@ -4021,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 @@ -4034,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==} @@ -4049,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: @@ -4067,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 @@ -4123,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: @@ -4142,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: @@ -4186,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): @@ -4578,7 +4423,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 +4439,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 +4461,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 +5950,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 +6136,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 +7285,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 +10220,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 @@ -12471,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 @@ -15823,17 +15649,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 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) diff --git a/specs/span-batches.md b/specs/span-batches.md index 1a006ac59..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,36 +73,69 @@ Introduce version `1` to the [batch-format](./derivation.md#batch-format) table: | 1 | `prefix ++ payload` | Notation: -`++`: concatenation of byte-strings. -`anchor`: first 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. `anchor.timestamp - config.genesis.timestamp`. - - `parent_check`: first 20 bytes of parent hash, i.e. `anchor.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]`. -- `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 @@ -100,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 @@ -114,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 @@ -144,40 +261,46 @@ 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. - - `end_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, - we may be past this L1 block in the safe L2 chain. + - `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. - 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: - `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`)