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.

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`)